package com.ruicar.afs.cloud.basic.common.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruicar.afs.cloud.basic.api.corporate.dto.CorporateTransferApprovedDTO;
import com.ruicar.afs.cloud.basic.api.corporate.dto.CorporateTransferApprovedDetailDTO;
import com.ruicar.afs.cloud.basic.api.corporate.dto.DealCorporateResultDto;
import com.ruicar.afs.cloud.basic.common.condition.ReceiptRecordCondition;
import com.ruicar.afs.cloud.basic.common.entity.*;
import com.ruicar.afs.cloud.basic.common.mapper.BasicReceiptRecordMapper;
import com.ruicar.afs.cloud.basic.common.service.*;
import com.ruicar.afs.cloud.basic.proceeds.debit.entity.BasicDebitBatchDetails;
import com.ruicar.afs.cloud.basic.proceeds.debit.entity.BasicDebitRecord;
import com.ruicar.afs.cloud.basic.proceeds.debit.service.BasicDebitRecordService;
import com.ruicar.afs.cloud.basic.proceeds.mq.sender.FinanceSender;
import com.ruicar.afs.cloud.batch.entity.AfsBatchInfo;
import com.ruicar.afs.cloud.common.core.constant.CommonConstants;
import com.ruicar.afs.cloud.common.core.security.service.AfsUser;
import com.ruicar.afs.cloud.common.core.security.util.SecurityUtils;
import com.ruicar.afs.cloud.common.core.util.IResponse;
import com.ruicar.afs.cloud.common.modules.afscorebusiness.enums.WhetherEnum;
import com.ruicar.afs.cloud.common.modules.constant.VoucherBuriedPointNo;
import com.ruicar.afs.cloud.common.modules.contract.enums.*;
import com.ruicar.afs.cloud.common.mq.finance.cancel.dto.CancelDetailDto;
import com.ruicar.afs.cloud.common.mq.finance.cancel.dto.CancelSuccessDto;
import com.ruicar.afs.cloud.common.mq.finance.cancel.dto.RefundSuccessDto;
import com.ruicar.afs.cloud.common.mq.finance.debit.dto.*;
import com.ruicar.afs.cloud.common.mq.rabbit.message.AfsTransEntity;
import com.ruicar.afs.cloud.common.mq.rabbit.message.MqTransCode;
import com.ruicar.afs.cloud.common.util.EmptyUtils;
import com.ruicar.afs.cloud.common.vo.*;
import com.ruicar.afs.cloud.manage.api.dto.OverpaymentDifferenceDTO;
import com.ruicar.afs.cloud.manage.api.feign.OverpaymentDifference.OverpaymentDifferenceFeign;
import com.ruicar.afs.cloud.manage.api.feign.cust.CustChangeFeign;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.MessageFormat;
import java.util.*;

/**
 * @author: Lee
 * @date 2020-05-30 04:35:07
 * @description
 */
@Service
@Slf4j
@AllArgsConstructor
@ConditionalOnProperty(prefix = "com.ruicar.afs.cloud.mq.rabbit", name = "enable")
public class BasicReceiptRecordServiceImpl extends ServiceImpl<BasicReceiptRecordMapper, BasicReceiptRecord> implements BasicReceiptRecordService {

    private final BasicCustBaseInfoService basicCustBaseInfoService;
    private final BasicExpenseRecordService basicExpenseRecordService;
    private final BasicRepaymentPlanService basicRepaymentPlanService;
    private final BasicAssetsRepaymentPlanService basicAssetsRepaymentPlanService;
    private final BasicReceiptDealDetailsService basicReceiptDealDetailsService;
    private final FinanceSender financeSender;
    private final BasicContractCustRelationService basicContractCustRelationService;
    private final BasicPenaltyInterestService basicPenaltyInterestService;
    private final BasicMainInfoService basicMainInfoService;
    private final BasicFinancialAgreementService basicFinancialAgreementService;
    private final BasicDebitInfoService basicDebitInfoService;
    private final BasicProductParamService basicProductParamService;
    private final BasicRevokeHandleService basicRevokeHandleService;
    private final BasicDebitRecordService basicDebitRecordService;
    private final CustChangeFeign custChangeFeign;
    private final OverpaymentDifferenceFeign OverpaymentDifferenceFeign;
    private final BasicPenaltyInterestDetailsService basicPenaltyInterestDetailsService;

    @Override
    public BasicReceiptRecord initReceiptRecordOfDebit(BasicDebitBatchDetails debitBatchDetails, WriteTargetTypeEnum writeTarget,Date batchDate) {
        BasicReceiptRecord basicReceiptRecord = new BasicReceiptRecord();
        /**  收据初始化时不关联虚拟账户id by ZC.GUO  **/
        basicReceiptRecord.setAccountId(null);

        basicReceiptRecord.setSourceType(ReceiptSourceTypeEnum.bankDeduct);
        basicReceiptRecord.setSourceTable(BasicDebitBatchDetails.class.getAnnotation(TableName.class).value());
        basicReceiptRecord.setSourceId(debitBatchDetails.getId());
        basicReceiptRecord.setArriveAmt(debitBatchDetails.getAmount());
        basicReceiptRecord.setUsedAmt(BigDecimal.ZERO);
        basicReceiptRecord.setUnusedAmt(basicReceiptRecord.getArriveAmt());
        basicReceiptRecord.setSourceAccountName(debitBatchDetails.getDebitAccountName());
        basicReceiptRecord.setSourceAccount(debitBatchDetails.getDebitAccount());
        basicReceiptRecord.setContractNo(debitBatchDetails.getContractNo());
        basicReceiptRecord.setCreditAccount(debitBatchDetails.getCreditAccount());
        basicReceiptRecord.setCreditBankName(debitBatchDetails.getCreditBankName());
        basicReceiptRecord.setCreditOpeningBankName(debitBatchDetails.getCreditOpeningBankName());
        basicReceiptRecord.setWriteTarget(writeTarget);
        basicReceiptRecord.setIsPrepay(WhetherEnum.NO.getCode());
        BasicContractCustRelation basicContractCustRelation = basicContractCustRelationService
                .getOne(Wrappers.<BasicContractCustRelation>query().lambda()
                        .eq(BasicContractCustRelation::getContractNo, debitBatchDetails.getContractNo())
                        .eq(BasicContractCustRelation::getCustRole, PersonRoleTypeEnum.MAIN_PERSON));
        BasicCustBaseInfo basicCustBaseInfo = basicCustBaseInfoService.getOne(Wrappers.<BasicCustBaseInfo>query().lambda()
                .eq(BasicCustBaseInfo::getCustNo, basicContractCustRelation.getCustNo()));
        basicReceiptRecord.setCustNo(basicCustBaseInfo.getCustNo());

        basicReceiptRecord.setReceiptStatus(ReceiptStatusEnum.debitSuccess);
        basicReceiptRecord.setSucceedTime(batchDate);
        basicReceiptRecord.setRevision(BigDecimal.ZERO.longValue());

        this.save(basicReceiptRecord);
        return basicReceiptRecord;
    }

    @Override
    public void sendDebitSuccessDataToFinance(BasicReceiptRecord basicReceiptRecord, TransOpreateTypeEnums operateType, String buriedPointNo, String operator) {
        /**  发送报文组装 by ZC.GUO  **/
        DebitSuccessDataDto debitSuccessDataDto = new DebitSuccessDataDto();
        debitSuccessDataDto.setCustNo(basicReceiptRecord.getCustNo());
        debitSuccessDataDto.setAmount(basicReceiptRecord.getArriveAmt());
        debitSuccessDataDto.setFundsType(FundsTypeEnum.surplus);
        debitSuccessDataDto.setFundId(basicReceiptRecord.getId());
        debitSuccessDataDto.setOperateType(operateType);
        debitSuccessDataDto.setReceiptSourceType(basicReceiptRecord.getSourceType());
        debitSuccessDataDto.setContractNo(basicReceiptRecord.getContractNo());
        debitSuccessDataDto.setOperator(operator);

        AfsTransEntity<DebitSuccessDataDto> entity = new AfsTransEntity<>();
        entity.setData(debitSuccessDataDto);
        entity.setTransCode(MqTransCode.AFS_CONTRACT_BASIC_FINANCE_CONTRACT_ARRIVE_SUCCESS);
        financeSender.sendDebitSuccessDataToFinance(entity);
    }

    @Override
    public List<BasicReceiptRecord> initReceiptRecordOfCorporateTransfer(CorporateTransferApprovedDTO corporateTransferApprovedDTO,Date batchDate) {

        /**  核销目的 by ZC.GUO  **/
        WriteTargetTypeEnum writeTarget = CaseTypeEnum.BEFORE_CHARGE.equals(corporateTransferApprovedDTO.getCaseType()) ? WriteTargetTypeEnum.beforeCharge : WriteTargetTypeEnum.normal;

        List<BasicReceiptRecord> receiptRecordList = new ArrayList<>();
        List<CorporateTransferApprovedDetailDTO> detailDTOList = corporateTransferApprovedDTO.getDetailDTOList();
        if (EmptyUtils.isNotEmpty(detailDTOList)) {
            for (CorporateTransferApprovedDetailDTO detail : detailDTOList) {
                BasicReceiptRecord basicReceiptRecord = new BasicReceiptRecord();
                /**  收据初始化时不关联虚拟账户id by ZC.GUO  **/
                basicReceiptRecord.setAccountId(null);

                basicReceiptRecord.setSourceType(ReceiptSourceTypeEnum.transferAccounts);
                basicReceiptRecord.setSourceTable(detail.getSourceTable());
                basicReceiptRecord.setSourceId(detail.getSourceId());
                basicReceiptRecord.setArriveAmt(detail.getArriveAmt());
                basicReceiptRecord.setUsedAmt(BigDecimal.ZERO);
                basicReceiptRecord.setUnusedAmt(basicReceiptRecord.getArriveAmt());
                basicReceiptRecord.setSourceAccountName(detail.getSourceAccountName());
                basicReceiptRecord.setSourceAccount(detail.getSourceAccount());
                basicReceiptRecord.setContractNo(detail.getContractNo());
                basicReceiptRecord.setCreditAccount(detail.getCreditAccount());
                basicReceiptRecord.setCreditBankName(detail.getCreditBankName());
                basicReceiptRecord.setCreditOpeningBankName(detail.getCreditOpeningBankName());
                basicReceiptRecord.setWriteTarget(writeTarget);
                basicReceiptRecord.setIsPrepay(WhetherEnum.NO.getCode());
                BasicContractCustRelation basicContractCustRelation = basicContractCustRelationService
                        .getOne(Wrappers.<BasicContractCustRelation>query().lambda()
                                .eq(BasicContractCustRelation::getContractNo, detail.getContractNo())
                                .eq(BasicContractCustRelation::getCustRole, PersonRoleTypeEnum.MAIN_PERSON));
                BasicCustBaseInfo basicCustBaseInfo = basicCustBaseInfoService.getOne(Wrappers.<BasicCustBaseInfo>query().lambda()
                        .eq(BasicCustBaseInfo::getCustNo, basicContractCustRelation.getCustNo()));
                basicReceiptRecord.setCustNo(basicCustBaseInfo.getCustNo());

                basicReceiptRecord.setReceiptStatus(ReceiptStatusEnum.debitSuccess);
                basicReceiptRecord.setSucceedTime(batchDate);
                basicReceiptRecord.setRevision(BigDecimal.ZERO.longValue());

                receiptRecordList.add(basicReceiptRecord);
            }
        }
        this.saveBatch(receiptRecordList);
        return receiptRecordList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public IResponse<DealCorporateResultDto> corporateTransferApproved(CorporateTransferApprovedDTO corporateTransferApprovedDTO, Date batchDate) {
        DealCorporateResultDto dealCorporateResultDto = new DealCorporateResultDto();

        BasicMainInfo basicMainInfo = basicMainInfoService.getOne(Wrappers.<BasicMainInfo>query().lambda()
                .eq(BasicMainInfo::getContractNo,corporateTransferApprovedDTO.getContractNo())
        );
        if (EmptyUtils.isEmpty(basicMainInfo)){
            dealCorporateResultDto.setDealResult("9999");
            return IResponse.fail("合同号不存在");
        }

        /**  新增收据 by ZC.GUO  **/
        List<BasicReceiptRecord> receiptRecordList =  this.initReceiptRecordOfCorporateTransfer(corporateTransferApprovedDTO,batchDate);

        if (EmptyUtils.isNotEmpty(receiptRecordList)){
            for (BasicReceiptRecord basicReceiptRecord:receiptRecordList){
                String buriedPointNo=null;
                if(WriteTargetTypeEnum.beforeCharge.equals(basicReceiptRecord.getWriteTarget())){
                    buriedPointNo=VoucherBuriedPointNo.corporateSettlementAdvance;
                }else{
                    buriedPointNo=VoucherBuriedPointNo.corporateSettlement;
                }
                /**  发送扣款成功数据到账务服务MQ by ZC.GUO  **/
                this.sendDebitSuccessDataToFinance(basicReceiptRecord,TransOpreateTypeEnums.publichandle,buriedPointNo,corporateTransferApprovedDTO.getOperator());
                /**  更新收据状态 by ZC.GUO  **/
                basicReceiptRecord.setReceiptStatus(ReceiptStatusEnum.creditSuccess);
                this.updateById(basicReceiptRecord);
            }
        }
        dealCorporateResultDto.setDealResult("0000");
        return IResponse.success(dealCorporateResultDto);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean arriveSuccessErrorHandle(String message) {

        JSONObject content = JSONObject.parseObject(JSONObject.parseObject(message).getString("content"));
        JSONObject debitSuccessData = content.getJSONObject("data");
        DebitSuccessDataDto debitSuccessDataDto = debitSuccessData.toJavaObject(DebitSuccessDataDto.class);
        if (debitSuccessDataDto != null) {
            boolean flag = false;
            while (!flag) {
                BasicReceiptRecord receiptRecord = this.getOne(Wrappers.<BasicReceiptRecord>query().lambda()
                        .eq(BasicReceiptRecord::getId, debitSuccessDataDto.getFundId())
                        .eq(BasicReceiptRecord::getReceiptStatus, ReceiptStatusEnum.creditSuccess)

                );
                if (receiptRecord != null) {
                    receiptRecord.setReceiptStatus(ReceiptStatusEnum.debitSuccess);
                    this.updateById(receiptRecord);
                    flag = true;
                }
            }
            return true;
        }
        return false;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean receiptHandleCompleteErrorHandle(String message) {

        /**  数据解析 by ZC.GUO  **/
        JSONObject content = JSONObject.parseObject(JSONObject.parseObject(message).getString("content"));
        JSONArray receiptHandleCompleteData = content.getJSONArray("data");

        List<ReceiptHandleCompleteDto> receiptHandleCompleteDtoList = receiptHandleCompleteData.toJavaList(ReceiptHandleCompleteDto.class);
        if (receiptHandleCompleteDtoList != null && receiptHandleCompleteDtoList.size() > 0) {
            for (ReceiptHandleCompleteDto receiptHandleCompleteDto : receiptHandleCompleteDtoList) {
                List<ReceiptHandleDetailDto> receiptHandleDetailDtoList = receiptHandleCompleteDto.getReceiptHandleDetailList();
                if (receiptHandleDetailDtoList != null && receiptHandleDetailDtoList.size() > 0) {
                    /**  逐条处理数据 by ZC.GUO  **/
                    for (ReceiptHandleDetailDto receiptHandleDetailDto : receiptHandleDetailDtoList) {
                        boolean flag = false;
                        while (!flag) {
                            BasicReceiptDealDetails receiptDealDetails = basicReceiptDealDetailsService.getOne(Wrappers.<BasicReceiptDealDetails>query().lambda()
                                    .eq(BasicReceiptDealDetails::getId, receiptHandleDetailDto.getReceiptDetailId())
                                    .eq(BasicReceiptDealDetails::getStatus, ReceiptStatusEnum.creditSuccess)
                            );
                            if (receiptDealDetails != null) {
                                receiptDealDetails.setStatus(ReceiptStatusEnum.debitSuccess);
                                basicReceiptDealDetailsService.updateById(receiptDealDetails);
                                flag = true;
                            }
                        }
                    }
                }
            }
            return true;
        }
        return false;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean handleReceiptByIdList(StartReceiptHandleDto startReceiptHandleDto,Date batchDate) {
        Map<Long, List<BasicReceiptDealDetails>> finalData = new HashMap<>(16);
        if (startReceiptHandleDto != null
                && startReceiptHandleDto.getIdList() != null
                && startReceiptHandleDto.getIdList().size() > 0) {
            List<BasicReceiptRecord> receiptRecordList = this.list(Wrappers.<BasicReceiptRecord>query().lambda()
                    .in(BasicReceiptRecord::getId, startReceiptHandleDto.getIdList())
                    .gt(BasicReceiptRecord::getUnusedAmt, BigDecimal.ZERO)
                    .orderByAsc(BasicReceiptRecord::getContractNo)
                    .orderByAsc(BasicReceiptRecord::getSucceedTime)
            );
            if (receiptRecordList != null && receiptRecordList.size() > 0) {
                for (BasicReceiptRecord receiptRecord : receiptRecordList) {
                    List<BasicReceiptDealDetails> receiptDealDetailsList = new ArrayList<>();
                    if (WriteTargetTypeEnum.beforeCharge.equals(receiptRecord.getWriteTarget())) {
                        /**  提前结清核销 by ZC.GUO  **/
                        receiptDealDetailsList = this.handleReceiptForBeforeCharge(receiptRecord,batchDate);

                    } else {
                        /**  正常核销 by ZC.GUO  **/
                        receiptDealDetailsList = this.handleReceiptForNormal(receiptRecord,batchDate);
                    }
                    List<BasicReceiptDealDetails> advancePaymentList = this.handleAdvancePayment(receiptRecord);
                    if (advancePaymentList != null && advancePaymentList.size() > 0) {
                        receiptDealDetailsList.addAll(advancePaymentList);
                    }
                    /**  数据归集 by ZC.GUO  **/
                    finalData.put(receiptRecord.getId(), receiptDealDetailsList);
                    /**  虚拟账户id更新 by ZC.GUO  **/
                    receiptRecord.setAccountId(receiptRecord.getAccountId() == null ? startReceiptHandleDto.getAccountId() : receiptRecord.getAccountId());
                    /**  借据和合同信息更新 by ZC.GUO  **/
                    basicDebitInfoService.reCalculateAfterReceipt(receiptRecord);
                    this.updateById(receiptRecord);
                }
            }
            /**  收据处理完成，通过MQ推送数据给账务服务 by ZC.GUO  **/
            this.sendHandleCompleteData(startReceiptHandleDto, finalData);
        }
        return true;
    }

    private void sendHandleCompleteData(StartReceiptHandleDto startReceiptHandleDto, Map<Long, List<BasicReceiptDealDetails>> finalData) {
        List<ReceiptHandleCompleteDto> receiptHandleCompleteDtoList = new ArrayList<>();
        for (Long receiptId : startReceiptHandleDto.getIdList()) {

            BasicReceiptRecord receiptRecord = this.getOne( Wrappers.<BasicReceiptRecord>query().lambda()
                    .eq( BasicReceiptRecord::getId, receiptId ) );
            BasicFinancialAgreement basicFinancialAgreement = basicFinancialAgreementService.getOne( Wrappers.<BasicFinancialAgreement>lambdaQuery()
                    .eq( BasicFinancialAgreement::getContractNo, receiptRecord.getContractNo() )
                    .eq( BasicFinancialAgreement::getCostType, AssetTypeEnum.CAR_AMT ) );
            //暂记账/表外金额
            BigDecimal suspenseAccount = basicFinancialAgreement.getSuspenseAccount() != null ? basicFinancialAgreement.getSuspenseAccount() : BigDecimal.ZERO;
            BigDecimal specialTemporary = basicFinancialAgreement.getSpecialTemporary() != null ? basicFinancialAgreement.getSpecialTemporary() : BigDecimal.ZERO;
            List<BasicReceiptDealDetails> receiptDealDetailsList = finalData.get( receiptId );
            /**  本次进行了处理 by ZC.GUO  **/
            if (receiptDealDetailsList != null && receiptDealDetailsList.size() > 0) {
                BigDecimal handleAmount = BigDecimal.ZERO;
                ArrayList<ReceiptHandleDetailDto> receiptHandleDetailDtoList = new ArrayList<>();
                BigDecimal totalInterest = BigDecimal.ZERO;
                for (BasicReceiptDealDetails receiptDealDetails : receiptDealDetailsList) {
                    /**  处理动作明细 by ZC.GUO  **/
                    ReceiptHandleDetailDto receiptHandleDetailDto = new ReceiptHandleDetailDto();
                    receiptHandleDetailDto.setFeeTypeEnum( receiptDealDetails.getReceiptType() );
                    receiptHandleDetailDto.setFeeSourceTable( receiptDealDetails.getDealTable() );
                    receiptHandleDetailDto.setFeeId( receiptDealDetails.getDealId() );
                    receiptHandleDetailDto.setReceiptDetailId( receiptDealDetails.getId() );
                    receiptHandleDetailDto.setAmount( receiptDealDetails.getDealAmt() );
                    if (FeeTypeEnum.interest.equals( receiptDealDetails.getReceiptType() )) {
                        totalInterest = totalInterest.add( receiptDealDetails.getDealAmt() );
                    }
                    receiptHandleDetailDtoList.add( receiptHandleDetailDto );

                    /**  处理金额累加 by ZC.GUO  **/
                    //未分配金额不累加
                    if (!FeeTypeEnum.unusedFund.equals( receiptDealDetails.getReceiptType() )) {
                        handleAmount = handleAmount.add( receiptDealDetails.getDealAmt() );
                    }
                }
                /**
                 *   判断表外金额和实收利息大小
                 *   表外金额>实收利息,转回金额=实收利息
                 *   表外金额<=实收利息,转回金额=表外金额
                 */

                if (totalInterest.compareTo( BigDecimal.ZERO ) > 0 && suspenseAccount.compareTo( BigDecimal.ZERO ) > 0) {
                    BigDecimal outAmt= receiptRecord.getOuterAmt()!=null? receiptRecord.getOuterAmt():BigDecimal.ZERO;
                    BigDecimal specialOutAmt= receiptRecord.getSpecialOuterAmt()!=null? receiptRecord.getSpecialOuterAmt():BigDecimal.ZERO;
                    FeeTypeEnum feeTypeEnum=null;
                    FeeTypeEnum specialFeeTypeEnum=null;
                    BigDecimal specialSuspense=BigDecimal.ZERO;
                    BigDecimal suspense=BigDecimal.ZERO;
                    //赞记账>实收利息
                    if (suspenseAccount.compareTo( totalInterest ) > 0 ) {
                        feeTypeEnum = FeeTypeEnum.temporaryInterest;
                        specialFeeTypeEnum=FeeTypeEnum.specialTemporary;
                    }else {
                        feeTypeEnum = FeeTypeEnum.clearInterest;
                        specialFeeTypeEnum=FeeTypeEnum.clearSpecial;
                    }
                    if(specialTemporary.compareTo( totalInterest ) >=0 ) {
                        specialSuspense=totalInterest;
                    }else if(specialTemporary.compareTo( totalInterest )<0&&specialSuspense.compareTo( totalInterest ) >=0 ) {
                        specialSuspense=specialTemporary;
                        suspense=totalInterest.subtract(specialTemporary);
                    }else if(specialTemporary.compareTo( totalInterest )<=0&&specialSuspense.compareTo( totalInterest )<0 ) {
                        specialSuspense=specialTemporary;
                        suspense=specialSuspense.subtract(specialTemporary);
                    }
                    //90天以上的暂记账
                    if(specialSuspense.compareTo( BigDecimal.ZERO )>0){
                        ReceiptHandleDetailDto receiptHandleDetailDto = new ReceiptHandleDetailDto();
                        receiptHandleDetailDto.setFeeSourceTable( basicFinancialAgreement.getClass().getAnnotation( TableName.class ).value() );
                        receiptHandleDetailDto.setFeeId( basicFinancialAgreement.getId() );
                        receiptHandleDetailDto.setFeeTypeEnum(specialFeeTypeEnum );
                        receiptHandleDetailDto.setAmount(specialSuspense );
                        receiptHandleDetailDtoList.add( receiptHandleDetailDto );
                    }
                    //90天以内的暂记账
                    if(suspense.compareTo( BigDecimal.ZERO )>0){
                        ReceiptHandleDetailDto receiptHandleDetailDto = new ReceiptHandleDetailDto();
                        receiptHandleDetailDto.setFeeSourceTable( basicFinancialAgreement.getClass().getAnnotation( TableName.class ).value() );
                        receiptHandleDetailDto.setFeeId( basicFinancialAgreement.getId() );
                        receiptHandleDetailDto.setFeeTypeEnum( feeTypeEnum);
                        receiptHandleDetailDto.setAmount( suspense );
                        receiptHandleDetailDtoList.add( receiptHandleDetailDto );
                    }

                    receiptRecord.setOuterAmt(outAmt.add(suspense).add(specialSuspense));
                    receiptRecord.setSpecialOuterAmt(specialOutAmt.add(suspense).add(specialSuspense));
                    basicFinancialAgreement.setSuspenseAccount( suspenseAccount.subtract(suspense).subtract(specialSuspense));
                    basicFinancialAgreement.setSpecialTemporary( specialTemporary.subtract(suspense));
                    basicFinancialAgreementService.updateById( basicFinancialAgreement );
                }
                BasicMainInfo info = basicMainInfoService.getOne( Wrappers.<BasicMainInfo>lambdaQuery().eq( BasicMainInfo::getContractNo, receiptRecord.getContractNo() ), false );

                /**  收据处理概况 by ZC.GUO  **/
                ReceiptHandleCompleteDto receiptHandleCompleteDto = new ReceiptHandleCompleteDto();
                receiptHandleCompleteDto.setDealerName(info.getChannelFullName());
                receiptHandleCompleteDto.setFinancialProducts(info.getProductName());
                receiptHandleCompleteDto.setBusinessType(info.getBusinessType());
                receiptHandleCompleteDto.setFinancialProducts(info.getProductName());
                //获取埋点编号
                String buriedPointNo = this.getBuriedPointNo(receiptRecord);
                receiptHandleCompleteDto.setBuriedPointNo(buriedPointNo);
                AfsUser user = SecurityUtils.getUser();
                receiptHandleCompleteDto.setOperator(user == null ? null : user.getUsername());
                receiptHandleCompleteDto.setReceiptId(receiptRecord.getId());
                receiptHandleCompleteDto.setHandleAmount(handleAmount);
                receiptHandleCompleteDto.setUnusedAmount(receiptRecord.getUnusedAmt());
                receiptHandleCompleteDto.setReceiptHandleDetailList(receiptHandleDetailDtoList);
                receiptHandleCompleteDto.setReceiptSourceType(receiptRecord.getSourceType());
                receiptHandleCompleteDto.setSourceAccount(receiptRecord.getSourceAccount());
                receiptHandleCompleteDto.setCreditAccount(receiptRecord.getCreditAccount());
                receiptHandleCompleteDto.setContractNo(startReceiptHandleDto.getContractNo());
                receiptHandleCompleteDtoList.add(receiptHandleCompleteDto);
            } else {
                /**  未进行处理 by ZC.GUO  **/
                ReceiptHandleCompleteDto receiptHandleCompleteDto = new ReceiptHandleCompleteDto();
                AfsUser user = SecurityUtils.getUser();
                receiptHandleCompleteDto.setOperator(user == null ? null : user.getUsername());
                receiptHandleCompleteDto.setHandleAmount(BigDecimal.ZERO);
                receiptHandleCompleteDto.setReceiptId(receiptRecord.getId());
                receiptHandleCompleteDto.setUnusedAmount(receiptRecord.getUnusedAmt());
                receiptHandleCompleteDto.setReceiptHandleDetailList(new ArrayList<>());
                receiptHandleCompleteDto.setReceiptSourceType(receiptRecord.getSourceType());
                receiptHandleCompleteDto.setSourceAccount(receiptRecord.getSourceAccount());
                receiptHandleCompleteDto.setCreditAccount(receiptRecord.getCreditAccount());
                receiptHandleCompleteDto.setContractNo(startReceiptHandleDto.getContractNo());
                receiptHandleCompleteDtoList.add(receiptHandleCompleteDto);
            }
            receiptRecord.setIsPrepay(WhetherEnum.YES.getCode());
            this.updateById(receiptRecord);
        }

        /**  发送数据封装 by ZC.GUO  **/
        ReceiptHandleCompletePackageDto receiptHandleCompletePackageDto = new ReceiptHandleCompletePackageDto();
        receiptHandleCompletePackageDto.setReceiptHandleCompleteList(receiptHandleCompleteDtoList);
        receiptHandleCompletePackageDto.setOperator(startReceiptHandleDto.getOperator());
        AfsTransEntity<ReceiptHandleCompletePackageDto> entity = new AfsTransEntity<>();
        entity.setData(receiptHandleCompletePackageDto);
        entity.setTransCode(MqTransCode.AFS_CONTRACT_BASIC_FINANCE_CONTRACT_RECEIPTHANDLE_COMPLETE);
        financeSender.sendReceiptHandleCompleteDataToFinance(entity);
    }

    @Override
    public List<BasicReceiptDealDetails> handleReceiptForNormal(BasicReceiptRecord receiptRecord,Date batchDate) {
        List<BasicReceiptDealDetails> receiptDealDetailsList = new ArrayList<>();
        /**  费用 by ZC.GUO  **/
        List<BasicExpenseRecord> urgeExpenseRecordList = basicExpenseRecordService.list(Wrappers.<BasicExpenseRecord>query().lambda()
                .eq(BasicExpenseRecord::getContractNo, receiptRecord.getContractNo())
                .eq(BasicExpenseRecord::getStatus, ExpenseStatusEnum.unsettle)
                .gt(BasicExpenseRecord::getRemainingAmt, BigDecimal.ZERO)
                .eq(BasicExpenseRecord::getCostType, FeeTypeEnum.urge)
        );
        List<BasicReceiptDealDetails> urgeReceiptDealDetailsList = this.handlePenaltyExpenseRecord(receiptRecord, urgeExpenseRecordList, DealSourceEnum.cost);
        if (urgeReceiptDealDetailsList != null && urgeReceiptDealDetailsList.size() > 0) {
            receiptDealDetailsList.addAll(urgeReceiptDealDetailsList);
        }

        List<BasicExpenseRecord> changeCostExpenseRecordList = basicExpenseRecordService.list(Wrappers.<BasicExpenseRecord>query().lambda()
                .eq(BasicExpenseRecord::getContractNo, receiptRecord.getContractNo())
                .eq(BasicExpenseRecord::getStatus, ExpenseStatusEnum.unsettle)
                .gt(BasicExpenseRecord::getRemainingAmt, BigDecimal.ZERO)
                .eq(BasicExpenseRecord::getCostType, FeeTypeEnum.changeCost)
        );
        List<BasicReceiptDealDetails> changeCostReceiptDealDetailsList = this.handlePenaltyExpenseRecord(receiptRecord, changeCostExpenseRecordList, DealSourceEnum.cost);
        if (changeCostReceiptDealDetailsList != null && changeCostReceiptDealDetailsList.size() > 0) {
            receiptDealDetailsList.addAll(changeCostReceiptDealDetailsList);
        }
        List<BasicExpenseRecord> changeExtraInterestExpenseRecordList = basicExpenseRecordService.list(Wrappers.<BasicExpenseRecord>query().lambda()
                .eq(BasicExpenseRecord::getContractNo, receiptRecord.getContractNo())
                .eq(BasicExpenseRecord::getStatus, ExpenseStatusEnum.unsettle)
                .gt(BasicExpenseRecord::getRemainingAmt, BigDecimal.ZERO)
                .eq(BasicExpenseRecord::getCostType, FeeTypeEnum.changeExtraInterest)
        );
        List<BasicReceiptDealDetails> changeExtraInterestReceiptDealDetailsList = this.handlePenaltyExpenseRecord(receiptRecord, changeExtraInterestExpenseRecordList, DealSourceEnum.cost);
        if (changeExtraInterestReceiptDealDetailsList != null && changeExtraInterestReceiptDealDetailsList.size() > 0) {
            receiptDealDetailsList.addAll(changeExtraInterestReceiptDealDetailsList);
        }

        List<BasicExpenseRecord> otherExpenseRecordList = basicExpenseRecordService.list(Wrappers.<BasicExpenseRecord>query().lambda()
                .eq(BasicExpenseRecord::getContractNo, receiptRecord.getContractNo())
                .eq(BasicExpenseRecord::getStatus, ExpenseStatusEnum.unsettle)
                .gt(BasicExpenseRecord::getRemainingAmt, BigDecimal.ZERO)
                .eq(BasicExpenseRecord::getCostType, FeeTypeEnum.other)
        );
        List<BasicReceiptDealDetails> otherReceiptDealDetailsList = this.handlePenaltyExpenseRecord(receiptRecord, otherExpenseRecordList, DealSourceEnum.cost);
        if (otherReceiptDealDetailsList != null && otherReceiptDealDetailsList.size() > 0) {
            receiptDealDetailsList.addAll(otherReceiptDealDetailsList);
        }
        /**  罚息 by ZC.GUO  **/
        List<BasicExpenseRecord> penaltyExpenseRecordList = basicExpenseRecordService.list(Wrappers.<BasicExpenseRecord>query().lambda()
                .eq(BasicExpenseRecord::getContractNo, receiptRecord.getContractNo())
                .eq(BasicExpenseRecord::getStatus, ExpenseStatusEnum.unsettle)
                .gt(BasicExpenseRecord::getRemainingAmt, BigDecimal.ZERO)
                .eq(BasicExpenseRecord::getCostType, FeeTypeEnum.penalty)
        );
        List<BasicReceiptDealDetails> penaltyReceiptDealDetailsList = this.handlePenaltyExpenseRecord(receiptRecord, penaltyExpenseRecordList, DealSourceEnum.penaltyInterest);
        if (penaltyReceiptDealDetailsList != null && penaltyReceiptDealDetailsList.size() > 0) {
            receiptDealDetailsList.addAll(penaltyReceiptDealDetailsList);
        }

        BasicFinancialAgreement basicFinancialAgreement = basicFinancialAgreementService.getOne(Wrappers.<BasicFinancialAgreement>lambdaQuery()
                .eq(BasicFinancialAgreement::getContractNo, receiptRecord.getContractNo())
                .eq(BasicFinancialAgreement::getCostType, AssetTypeEnum.CAR_AMT));

        /**  逾期和当天应还 by ZC.GUO  **/
        List<RepaymentStatusEnum> statusEnumList = new ArrayList<>();
        statusEnumList.add(RepaymentStatusEnum.UNPAID);
        statusEnumList.add(RepaymentStatusEnum.OVERDUE);
        List<BasicRepaymentPlan> couldHandlePlanList = basicRepaymentPlanService.list(Wrappers.<BasicRepaymentPlan>query().lambda()
                .eq(BasicRepaymentPlan::getContractNo, receiptRecord.getContractNo())
                .in(BasicRepaymentPlan::getStatus, statusEnumList)
                .le(BasicRepaymentPlan::getDueDate, DateUtil.endOfDay(batchDate))
                .orderByAsc(BasicRepaymentPlan::getDueDate, BasicRepaymentPlan::getTermNo)
        );
        /**  合同逾期天数判断 by ZC.GUO  **/
        BasicDebitInfo debitInfo = basicDebitInfoService.getOne(Wrappers.<BasicDebitInfo>query().lambda()
                .eq(BasicDebitInfo::getContractNo,receiptRecord.getContractNo())
        );
        /**  90天以下，时间久的优先，先利后本 by ZC.GUO  **/
        if (EmptyUtils.isNotEmpty(debitInfo)&&debitInfo.getCurrentAbsoluteOverdue()<=90){
            List<BasicReceiptDealDetails> rentReceiptDealDetailsList = this.handleRepaymentPlan(basicFinancialAgreement,receiptRecord, couldHandlePlanList, RentTypeEnum.rent,batchDate);
            if (EmptyUtils.isNotEmpty(rentReceiptDealDetailsList)) {
                receiptDealDetailsList.addAll(rentReceiptDealDetailsList);
            }
        }
        /**  90天以上，时间久的优先，先本后利 by ZC.GUO  **/
        else{
            /**  本金 by ZC.GUO  **/
            List<BasicReceiptDealDetails> capitalReceiptDealDetailsList = this.handleRepaymentPlan(basicFinancialAgreement, receiptRecord, couldHandlePlanList, RentTypeEnum.capital,batchDate);
            if (EmptyUtils.isNotEmpty(capitalReceiptDealDetailsList)) {
                receiptDealDetailsList.addAll(capitalReceiptDealDetailsList);
            }
            /**  利息 by ZC.GUO  **/
            List<BasicReceiptDealDetails> interestReceiptDealDetailsList = this.handleRepaymentPlan(basicFinancialAgreement,receiptRecord, couldHandlePlanList, RentTypeEnum.interest,batchDate);
            if (EmptyUtils.isNotEmpty(interestReceiptDealDetailsList)) {
                receiptDealDetailsList.addAll(interestReceiptDealDetailsList);
            }
        }
        /**  未到期 by ZC.GUO  **/
        BasicProductParam productParam = basicProductParamService.getOne(Wrappers.<BasicProductParam>lambdaQuery()
                .eq(BasicProductParam::getContractNo, receiptRecord.getContractNo())
                .eq(BasicProductParam::getAtomKey, ProductAtomEnum.RATE_TYPE)
                .eq(BasicProductParam::getProductId, basicFinancialAgreement.getProductId()));
        if (EmptyUtils.isNotEmpty(productParam)) {
            /**  非LPR 顺序冲抵 by ZC.GUO  **/
            if (CommonConstants.COMMON_NO.equals(productParam.getAtomValue())) {
                List<BasicRepaymentPlan> undueRepaymentPlanList = basicRepaymentPlanService.list(Wrappers.<BasicRepaymentPlan>query().lambda()
                        .eq(BasicRepaymentPlan::getContractNo, receiptRecord.getContractNo())
                        .eq(BasicRepaymentPlan::getStatus, RepaymentStatusEnum.UNPAID)
                        /**  未到期 by ZC.GUO  **/
                        .gt(BasicRepaymentPlan::getDueDate, DateUtil.endOfDay(batchDate))
                        .orderByAsc(BasicRepaymentPlan::getDueDate)
                );
                List<BasicReceiptDealDetails> undueRentReceiptDealDetailsList = this.handleRepaymentPlan(basicFinancialAgreement,receiptRecord, undueRepaymentPlanList, RentTypeEnum.rent,batchDate);
                if (undueRentReceiptDealDetailsList != null && undueRentReceiptDealDetailsList.size() > 0) {
                    receiptDealDetailsList.addAll(undueRentReceiptDealDetailsList);
                }
            }
        }
        return receiptDealDetailsList;
    }

    @Override
    public List<BasicReceiptDealDetails> handleReceiptForBeforeCharge(BasicReceiptRecord receiptRecord,Date batchDate) {
        List<BasicReceiptDealDetails> receiptDealDetailsList = new ArrayList<>();
        /**  费用处理 by ZC.GUO  **/
        List<BasicExpenseRecord> urgeExpenseRecordList = basicExpenseRecordService.list(Wrappers.<BasicExpenseRecord>query().lambda()
                .eq(BasicExpenseRecord::getContractNo, receiptRecord.getContractNo())
                .eq(BasicExpenseRecord::getStatus, ExpenseStatusEnum.unsettle)
                .gt(BasicExpenseRecord::getRemainingAmt, BigDecimal.ZERO)
                .ne(BasicExpenseRecord::getCostType, FeeTypeEnum.penalty)
        );
        List<BasicReceiptDealDetails> urgeReceiptDealDetailsList = this.handlePenaltyExpenseRecord(receiptRecord, urgeExpenseRecordList, DealSourceEnum.cost);
        if (urgeReceiptDealDetailsList != null && urgeReceiptDealDetailsList.size() > 0) {
            receiptDealDetailsList.addAll(urgeReceiptDealDetailsList);
        }
        /**  罚息处理 by ZC.GUO  **/
        List<BasicExpenseRecord> penaltyExpenseRecordList = basicExpenseRecordService.list(Wrappers.<BasicExpenseRecord>query().lambda()
                .eq(BasicExpenseRecord::getContractNo, receiptRecord.getContractNo())
                .eq(BasicExpenseRecord::getStatus, ExpenseStatusEnum.unsettle)
                .gt(BasicExpenseRecord::getRemainingAmt, BigDecimal.ZERO)
                .eq(BasicExpenseRecord::getCostType, FeeTypeEnum.penalty)
        );
        List<BasicReceiptDealDetails> penaltyReceiptDealDetailsList = this.handlePenaltyExpenseRecord(receiptRecord, penaltyExpenseRecordList, DealSourceEnum.penaltyInterest);
        if (penaltyReceiptDealDetailsList != null && penaltyReceiptDealDetailsList.size() > 0) {
            receiptDealDetailsList.addAll(penaltyReceiptDealDetailsList);
        }
        /**  还款计划处理 by ZC.GUO  **/
        List<RepaymentStatusEnum> statusEnumList = new ArrayList<>();
        statusEnumList.add(RepaymentStatusEnum.UNPAID);
        statusEnumList.add(RepaymentStatusEnum.OVERDUE);
        List<BasicRepaymentPlan> repaymentPlanList = basicRepaymentPlanService.list(Wrappers.<BasicRepaymentPlan>query().lambda()
                .eq(BasicRepaymentPlan::getContractNo, receiptRecord.getContractNo())
                .in(BasicRepaymentPlan::getStatus, statusEnumList)
                .orderByAsc(BasicRepaymentPlan::getTermNo)
                .orderByAsc(BasicRepaymentPlan::getDueDate)

        );
        BasicFinancialAgreement basicFinancialAgreement = basicFinancialAgreementService.getOne(Wrappers.<BasicFinancialAgreement>lambdaQuery()
                .eq(BasicFinancialAgreement::getContractNo, receiptRecord.getContractNo())
                .eq(BasicFinancialAgreement::getCostType, AssetTypeEnum.CAR_AMT));
        if (EmptyUtils.isNotEmpty(repaymentPlanList)) {
            for (BasicRepaymentPlan repaymentPlan : repaymentPlanList) {
                List<BasicRepaymentPlan> undueRepaymentPlanList = new ArrayList<>();
                List<BasicReceiptDealDetails> planDealDetailList = null;
                /**  逾期还款计划处理 by ZC.GUO  **/
                if (RepaymentStatusEnum.OVERDUE.equals(repaymentPlan.getStatus())) {
                    undueRepaymentPlanList.add(repaymentPlan);
                    planDealDetailList = this.handleRepaymentPlan(basicFinancialAgreement,receiptRecord, undueRepaymentPlanList, RentTypeEnum.rent,batchDate);
                    if (planDealDetailList != null && planDealDetailList.size() > 0) {
                        receiptDealDetailsList.addAll(planDealDetailList);
                    }
                } else {
                    BasicRepaymentPlan lastPlan = basicRepaymentPlanService.getOne(Wrappers.<BasicRepaymentPlan>query().lambda()
                            .eq(BasicRepaymentPlan::getContractNo, receiptRecord.getContractNo())
                            .in(BasicRepaymentPlan::getTermNo, repaymentPlan.getTermNo() - 1));
                    /**  当期还款计划处理 by ZC.GUO  **/
                    if (EmptyUtils.isEmpty(lastPlan)
                            || (lastPlan.getDueDate().before(batchDate) && repaymentPlan.getDueDate().after(batchDate))) {
                        /**  当期利息处理 by ZC.GUO  **/
                        IResponse<BigDecimal> response = custChangeFeign.getPrepaymentInterestByContractNo(receiptRecord.getContractNo());
                        if (CommonConstants.SUCCESS.equals(response.getCode())) {
                            BigDecimal interestReceivable = response.getData();
                            if (EmptyUtils.isNotEmpty(interestReceivable)&& interestReceivable.compareTo(repaymentPlan.getActualInterest())>0){
                                planDealDetailList = this.handleInterestForBeforeCharge(interestReceivable,receiptRecord,repaymentPlan,batchDate);
                                if (planDealDetailList != null && planDealDetailList.size() > 0) {
                                    receiptDealDetailsList.addAll(planDealDetailList);
                                }
                            }
                        }
                        /**  当期本金处理 by ZC.GUO  **/
                        undueRepaymentPlanList.add(repaymentPlan);
                        planDealDetailList = this.handleRepaymentPlan(basicFinancialAgreement,receiptRecord, undueRepaymentPlanList, RentTypeEnum.capital,batchDate);
                        if (planDealDetailList != null && planDealDetailList.size() > 0) {
                            receiptDealDetailsList.addAll(planDealDetailList);
                        }

                    }
                    /**  未到期还款计划处理 by ZC.GUO  **/
                    else {
                        undueRepaymentPlanList.add(repaymentPlan);
                        planDealDetailList = this.handleRepaymentPlan(basicFinancialAgreement,receiptRecord, undueRepaymentPlanList, RentTypeEnum.capital,batchDate);
                        if (planDealDetailList != null && planDealDetailList.size() > 0) {
                            receiptDealDetailsList.addAll(planDealDetailList);
                        }
                    }
                }
            }
        }
        return receiptDealDetailsList;
    }

    private void sendRefundInfoToMq(BasicReceiptRecord receiptRecord, String operator) {
        RefundSuccessDto refundSuccessDto = new RefundSuccessDto();
        refundSuccessDto.setReceiptId(receiptRecord.getId());
        refundSuccessDto.setCustNo(receiptRecord.getCustNo());
        refundSuccessDto.setSourceType(receiptRecord.getSourceType());
        refundSuccessDto.setRefundAmt(receiptRecord.getArriveAmt());
        refundSuccessDto.setContractNo(receiptRecord.getContractNo());
        refundSuccessDto.setOperator(operator);

        AfsTransEntity<RefundSuccessDto> entity = new AfsTransEntity<>();
        entity.setData(refundSuccessDto);
        entity.setTransCode(MqTransCode.AFS_CONTRACT_BASIC_FINANCE_CONTRACT_REFUND_AGREE);
        financeSender.sendReceiptRefundDataToFinance(entity);
    }

    @Override
    public boolean handleReceiptForRefund(Long id, String operator) {
        /**  收据表相关处理（退款不对收据表进行处理） by ZC.GUO  **/
        BasicReceiptRecord receiptRecord = this.getById(id);
        if (EmptyUtils.isEmpty(receiptRecord)) {
            log.info("收据退款处理失败，不存在的收据id：{}", id);
            return false;
        }
        /**  发送mq进行账务处理 by ZC.GUO  **/
        this.sendRefundInfoToMq(receiptRecord, operator);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public IResponse handleReceiptForCancel(Long id, String operator, AfsBatchInfo afsBatchInfo,Date batchDate) {
        /**  收据表相关处理 by ZC.GUO  **/
        BasicReceiptRecord receiptRecord = this.getById(id);
        if (EmptyUtils.isEmpty(receiptRecord)) {
            log.info("收据撤销处理失败，不存在的收据id：{}", id);
            return IResponse.fail(MessageFormat.format("收据撤销处理失败，不存在的收据id：{0}", id));
        }

        if (ReceiptStatusEnum.revoke.equals(receiptRecord.getReceiptStatus())) {
            log.info("收据撤销处理失败，重复进行撤销，id：{}", id);
            return IResponse.fail(MessageFormat.format("收据撤销处理失败，重复进行撤销，id：{0}", id));
        }

        //判断流程发起时，是否时按照时间顺序倒叙撤销，或流程已在流程中不可撤销
        List<BasicReceiptRecord> list = this.list(Wrappers.<BasicReceiptRecord>query().lambda().eq(BasicReceiptRecord::getContractNo, receiptRecord.getContractNo())
                .ne(BasicReceiptRecord::getId, id).
                        and(wrapper1 -> wrapper1.gt(BasicReceiptRecord::getCreateTime, receiptRecord.getSucceedTime()).eq(BasicReceiptRecord::getReceiptStatus, ReceiptStatusEnum.creditSuccess)
                                .or(wrapper2 -> wrapper2.eq(BasicReceiptRecord::getReceiptStatus, ReceiptStatusEnum.revokeExamine))
                        ));
        if (EmptyUtils.isNotEmpty(list)) {
            BasicReceiptRecord record = list.get(0);
            log.error(MessageFormat.format("本次撤销不可通过:{0}", record.getReceiptStatus().equals(ReceiptStatusEnum.creditSuccess) ? "需要按照时间顺序倒叙撤销" : "已有撤销合同在流程中"));
            return IResponse.fail(MessageFormat.format("本次撤销不可通过:{0}", record.getReceiptStatus().equals(ReceiptStatusEnum.creditSuccess) ? "需要按照时间顺序倒叙撤销" : "已有撤销合同在流程中"));
        }
        BasicMainInfo basicMainInfo = basicMainInfoService.getOne(Wrappers.<BasicMainInfo>query().lambda()
                .eq(BasicMainInfo::getContractNo,receiptRecord.getContractNo())
        );
        if (EmptyUtils.isEmpty(basicMainInfo) ){
            return IResponse.fail("合同号不存在");
        }else if( basicMainInfo.getCloseDate()!=null){
            return IResponse.fail("合同已关闭");
        }
        //微信和代扣保存处理数据
        if (ReceiptSourceTypeEnum.wechatRepayment.equals(receiptRecord.getSourceType()) || ReceiptSourceTypeEnum.bankDeduct.equals(receiptRecord.getSourceType())) {
            basicRevokeHandleService.saveBasicRevokeHandle(receiptRecord);
        }
        receiptRecord.setReceiptStatus(ReceiptStatusEnum.revoke);
        receiptRecord.setUndoEndTime(new Date());
        this.updateById(receiptRecord);
        /**  收据明细相关处理 by ZC.GUO  **/
        List<BasicReceiptDealDetails> receiptDealDetailsList = basicReceiptDealDetailsService.handleReceiptDetailForCancel(receiptRecord.getId(),afsBatchInfo,batchDate);
        this.updateContractStatus(receiptRecord.getContractNo(),receiptRecord.getWriteTarget());
        /**  发送mq进行账务处理 by ZC.GUO  **/
        this.sendCancelInfoToMq(receiptRecord, receiptDealDetailsList, operator);
        return IResponse.success(Boolean.TRUE);
    }

    private void sendCancelInfoToMq(BasicReceiptRecord receiptRecord, List<BasicReceiptDealDetails> receiptDealDetailsList, String operator) {
        CancelSuccessDto cancelSuccessDto = new CancelSuccessDto();
        cancelSuccessDto.setReceiptId(receiptRecord.getId());
        cancelSuccessDto.setCustNo(receiptRecord.getCustNo());
        cancelSuccessDto.setSourceType(receiptRecord.getSourceType());
        cancelSuccessDto.setCancelAmt(receiptRecord.getArriveAmt());
        cancelSuccessDto.setUsedAmt(receiptRecord.getUsedAmt());
        cancelSuccessDto.setUnusedAmt(receiptRecord.getUnusedAmt());
        cancelSuccessDto.setContractNo(receiptRecord.getContractNo());
        cancelSuccessDto.setOperator(operator);
        BasicMainInfo info = basicMainInfoService.getOne(Wrappers.<BasicMainInfo>lambdaQuery().eq(BasicMainInfo::getContractNo, receiptRecord.getContractNo()), false);
        if (WriteTargetTypeEnum.beforeCharge.equals(receiptRecord.getWriteTarget())) {
            if (ReceiptSourceTypeEnum.transferAccounts.equals(receiptRecord.getSourceType())) {
                cancelSuccessDto.setBuriedPointNo(VoucherBuriedPointNo.corporateSettlementAdvanceRevoke);
            } else {
                cancelSuccessDto.setBuriedPointNo(VoucherBuriedPointNo.settlementAdvanceRevoke);
            }
        } else {
            if (ReceiptSourceTypeEnum.transferAccounts.equals(receiptRecord.getSourceType())) {
                cancelSuccessDto.setBuriedPointNo(VoucherBuriedPointNo.corporateRevokeRent);
            } else {
                cancelSuccessDto.setBuriedPointNo(VoucherBuriedPointNo.revokeRent);
            }
        }

        cancelSuccessDto.setDealerName(info.getChannelFullName());
        cancelSuccessDto.setFinancialProducts(info.getProductName());
        cancelSuccessDto.setBusinessType(info.getBusinessType());
        cancelSuccessDto.setOperator(operator);
        List<CancelDetailDto> cancelDetailDtoList = new ArrayList<>();
        if (EmptyUtils.isNotEmpty( receiptDealDetailsList )) {
            BasicFinancialAgreement basicFinancialAgreement = basicFinancialAgreementService.getOne( Wrappers.<BasicFinancialAgreement>lambdaQuery()
                    .eq( BasicFinancialAgreement::getContractNo, receiptRecord.getContractNo() )
                    .eq( BasicFinancialAgreement::getCostType, AssetTypeEnum.CAR_AMT ) );
            //暂记账/表外金额
            BigDecimal suspenseAccount = basicFinancialAgreement.getSuspenseAccount() != null ? basicFinancialAgreement.getSuspenseAccount() : BigDecimal.ZERO;
            BigDecimal specialTemporary = basicFinancialAgreement.getSpecialTemporary() != null ? basicFinancialAgreement.getSpecialTemporary() : BigDecimal.ZERO;
            BigDecimal outAmt = receiptRecord.getOuterAmt() != null ? receiptRecord.getOuterAmt() : BigDecimal.ZERO;
            BigDecimal specialOuterAmt = receiptRecord.getSpecialOuterAmt() != null ? receiptRecord.getSpecialOuterAmt() : BigDecimal.ZERO;
            for (BasicReceiptDealDetails receiptDealDetails : receiptDealDetailsList) {
                CancelDetailDto cancelDetailDto = new CancelDetailDto();
                cancelDetailDto.setFeeType(receiptDealDetails.getReceiptType());
                cancelDetailDto.setFeeSourceTable(receiptDealDetails.getDealTable());
                cancelDetailDto.setFeeId(receiptDealDetails.getDealId());
                cancelDetailDto.setReceiptDetailId(receiptDealDetails.getId());
                cancelDetailDto.setAmount(receiptDealDetails.getDealAmt());
                cancelDetailDtoList.add(cancelDetailDto);
            }
            FeeTypeEnum feeTypeEnum=null;
            FeeTypeEnum specialFeeTypeEnum=null;
            //赞记账>实收利息
            if (suspenseAccount.compareTo( BigDecimal.ZERO ) > 0) {
                feeTypeEnum = FeeTypeEnum.temporaryInterest;
                specialFeeTypeEnum=FeeTypeEnum.specialTemporary;
            }else {
                feeTypeEnum = FeeTypeEnum.clearInterest;
                specialFeeTypeEnum=FeeTypeEnum.clearSpecial;
            }
            /**
             *   判断表外金额
             */
            if (outAmt.compareTo( BigDecimal.ZERO ) > 0 ) {
                CancelDetailDto cancelDetailDto = new CancelDetailDto();
                cancelDetailDto.setFeeSourceTable( basicFinancialAgreement.getClass().getAnnotation( TableName.class ).value() );
                cancelDetailDto.setFeeId( basicFinancialAgreement.getId() );
                cancelDetailDto.setFeeType(feeTypeEnum);
                cancelDetailDto.setAmount( outAmt.subtract(specialOuterAmt) );
                cancelDetailDtoList.add( cancelDetailDto );
            }
            /**
             *   判断特须表外金额
             */
            if (specialOuterAmt.compareTo( BigDecimal.ZERO ) > 0 ) {
                CancelDetailDto cancelDetailDto = new CancelDetailDto();
                cancelDetailDto.setFeeSourceTable( basicFinancialAgreement.getClass().getAnnotation( TableName.class ).value() );
                cancelDetailDto.setFeeId( basicFinancialAgreement.getId() );
                cancelDetailDto.setFeeType(specialFeeTypeEnum );
                cancelDetailDto.setAmount( specialOuterAmt );
                cancelDetailDtoList.add( cancelDetailDto );
            }
            basicFinancialAgreement.setSuspenseAccount(suspenseAccount.add(outAmt) );
            basicFinancialAgreement.setSpecialTemporary( specialTemporary.add(specialOuterAmt) );
            basicFinancialAgreementService.updateById( basicFinancialAgreement );
        }
        cancelSuccessDto.setDetails( cancelDetailDtoList );
        AfsTransEntity<CancelSuccessDto> entity = new AfsTransEntity<>();
        entity.setData(cancelSuccessDto);
        entity.setTransCode(MqTransCode.AFS_CONTRACT_BASIC_FINANCE_CONTRACT_CANCEL_AGREE);
        financeSender.sendReceiptCancelDataToFinance(entity);
    }

    /**
     * 罚息、费用核销
     *
     * @param
     * @return
     * @author ZC.GUO
     */
    private List<BasicReceiptDealDetails> handlePenaltyExpenseRecord(BasicReceiptRecord receiptRecord, List<BasicExpenseRecord> penaltyExpenseRecordList, DealSourceEnum dealSourceEnum) {
        List<BasicReceiptDealDetails> penaltyReceiptDealDetailsList = new ArrayList<>();
        if (penaltyExpenseRecordList != null && penaltyExpenseRecordList.size() > 0) {

            for (BasicExpenseRecord expenseRecord : penaltyExpenseRecordList) {
                /**  未分配金额大于0进行分配 by ZC.GUO  **/
                if (receiptRecord.getUnusedAmt().compareTo(BigDecimal.ZERO) > 0) {
                    /**  本次分配金额 by ZC.GUO  **/
                    BigDecimal amount = receiptRecord.getUnusedAmt();
                    if (amount.compareTo(expenseRecord.getRemainingAmt()) > 0) {
                        amount = expenseRecord.getRemainingAmt();
                    }
                    /**  生成收据明细 by ZC.GUO  **/
                    BasicReceiptDealDetails receiptDealDetails = new BasicReceiptDealDetails();
                    receiptDealDetails.setReceiptId(receiptRecord.getId());
                    receiptDealDetails.setDealType(DealTypeEnum.normal);
                    receiptDealDetails.setReceiptType(expenseRecord.getCostType());
                    receiptDealDetails.setDealSource(dealSourceEnum);
                    receiptDealDetails.setDealTable(BasicExpenseRecord.class.getAnnotation(TableName.class).value());
                    receiptDealDetails.setDealId(expenseRecord.getId());
                    receiptDealDetails.setContractNo(expenseRecord.getContractNo());
                    receiptDealDetails.setTermNo(null);
                    receiptDealDetails.setDealAmt(amount);
                    /**  TODO ZC.GUO  税金使用价税分离配置 **/
                    receiptDealDetails.setTax(amount.divide(BigDecimal.ONE.add(new BigDecimal("0.06")), 2, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal("0.06")));
                    receiptDealDetails.setStatus(ReceiptStatusEnum.creditSuccess);
                    basicReceiptDealDetailsService.save(receiptDealDetails);
                    penaltyReceiptDealDetailsList.add(receiptDealDetails);

                    /**  处理还款数据 by ZC.GUO  **/
                    basicExpenseRecordService.handleExpenseRecord(receiptDealDetails,expenseRecord, amount, receiptRecord.getId());
                    /**  处理收据 by ZC.GUO  **/
                    receiptRecord.setUsedAmt(receiptRecord.getUsedAmt().add(amount));
                    receiptRecord.setUnusedAmt(receiptRecord.getUnusedAmt().subtract(amount));
                }
            }

        }
        return penaltyReceiptDealDetailsList;
    }

    /**
     * 租金处理，先利后本
     *
     * @param
     * @return
     * @author ZC.GUO
     */
    private List<BasicReceiptDealDetails> handleInterestForBeforeCharge(BigDecimal thisInterest, BasicReceiptRecord receiptRecord, BasicRepaymentPlan repaymentPlan,Date batchDate) {
        List<BasicReceiptDealDetails> penaltyReceiptDealDetailsList = new ArrayList<>();
        if (EmptyUtils.isEmpty(repaymentPlan.getActualRent())) {
            repaymentPlan.setActualRent(BigDecimal.ZERO);
        }
        if (EmptyUtils.isEmpty(repaymentPlan.getActualPrinciple())) {
            repaymentPlan.setActualPrinciple(BigDecimal.ZERO);
        }
        if (EmptyUtils.isEmpty(repaymentPlan.getActualInterest())) {
            repaymentPlan.setActualInterest(BigDecimal.ZERO);
        }
        /**  处理利息 by ZC.GUO  **/
        /**  本次分配金额 by ZC.GUO  **/
        BigDecimal amount = receiptRecord.getUnusedAmt();

        if (amount.compareTo(thisInterest.subtract(repaymentPlan.getActualInterest())) > 0) {
            amount = thisInterest.subtract(repaymentPlan.getActualInterest());
        }
        repaymentPlan.setActualRent(repaymentPlan.getActualRent().add(amount));
        repaymentPlan.setActualInterest(repaymentPlan.getActualInterest().add(amount));

        /**  收据明细 by ZC.GUO  **/
        BasicReceiptDealDetails receiptDealDetails = new BasicReceiptDealDetails();
        receiptDealDetails.setReceiptId(receiptRecord.getId());
        if (repaymentPlan.getDueDate().before(DateUtil.endOfDay(batchDate))) {
            receiptDealDetails.setDealType(DealTypeEnum.normal);
        } else {
            receiptDealDetails.setDealType(DealTypeEnum.orderOffset);
        }
        receiptDealDetails.setReceiptType(FeeTypeEnum.interest);
        receiptDealDetails.setDealSource(DealSourceEnum.repaymentPlan);
        receiptDealDetails.setDealTable(BasicRepaymentPlan.class.getAnnotation(TableName.class).value());
        receiptDealDetails.setDealId(repaymentPlan.getId());
        receiptDealDetails.setContractNo(repaymentPlan.getContractNo());
        receiptDealDetails.setTermNo(repaymentPlan.getTermNo());
        receiptDealDetails.setDealAmt(amount);
        /**  TODO ZC.GUO  税金使用价税分离配置 **/
        receiptDealDetails.setTax(amount.divide(BigDecimal.ONE.add(new BigDecimal("0.06")), 2, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal("0.06")));
        receiptDealDetails.setStatus(ReceiptStatusEnum.creditSuccess);
        basicReceiptDealDetailsService.save(receiptDealDetails);
        penaltyReceiptDealDetailsList.add(receiptDealDetails);

        /**  收据处理 by ZC.GUO  **/
        receiptRecord.setUsedAmt(receiptRecord.getUsedAmt().add(amount));
        receiptRecord.setUnusedAmt(receiptRecord.getUnusedAmt().subtract(amount));

        /**  利息处理 by ZC.GUO  **/
        basicAssetsRepaymentPlanService.handleInterest(receiptDealDetails,repaymentPlan, amount,repaymentPlan.getActualInterest(),thisInterest, receiptRecord.getWriteTarget(),batchDate);
        /**  月供状态 by ZC.GUO  **/
        if ((repaymentPlan.getReceivableRent().subtract(repaymentPlan.getActualRent())).compareTo(BigDecimal.ZERO) <= 0) {
            repaymentPlan.setStatus(RepaymentStatusEnum.REPAID);
            repaymentPlan.setActualPaymentDate(batchDate);
        }
        /**  如果是提前还款并且本金已结清 by ZC.GUO  **/
        if (WriteTargetTypeEnum.beforeCharge.equals(receiptRecord.getWriteTarget()) && repaymentPlan.getReceivablePrinciple().compareTo(repaymentPlan.getActualPrinciple()) <= 0) {
            repaymentPlan.setStatus(RepaymentStatusEnum.PREPAYMENT);
            repaymentPlan.setActualPaymentDate(batchDate);
        }
        basicRepaymentPlanService.updateById(repaymentPlan);
        return penaltyReceiptDealDetailsList;
    }

    /**
     * 租金处理，先利后本
     *
     * @param
     * @return
     * @author ZC.GUO
     */
    private List<BasicReceiptDealDetails> handleRepaymentPlan(BasicFinancialAgreement basicFinancialAgreement, BasicReceiptRecord receiptRecord, List<BasicRepaymentPlan> repaymentPlanList, RentTypeEnum rentTypeEnum,Date batchDate) {
        List<BasicReceiptDealDetails> penaltyReceiptDealDetailsList = new ArrayList<>();
        if (repaymentPlanList != null && repaymentPlanList.size() > 0) {
            BigDecimal specificProvisions = BigDecimal.ZERO;
            for (BasicRepaymentPlan repaymentPlan : repaymentPlanList) {
                /**  空值处理 by ZC.GUO  **/
                if (EmptyUtils.isEmpty(repaymentPlan.getActualRent())) {
                    repaymentPlan.setActualRent(BigDecimal.ZERO);
                }
                if (EmptyUtils.isEmpty(repaymentPlan.getActualPrinciple())) {
                    repaymentPlan.setActualPrinciple(BigDecimal.ZERO);
                }
                if (EmptyUtils.isEmpty(repaymentPlan.getActualInterest())) {
                    repaymentPlan.setActualInterest(BigDecimal.ZERO);
                }
                /**  处理利息 by ZC.GUO  **/
                /**  未分配金额大于0且需要处理的是租金或利息，进行分配 by ZC.GUO  **/
                boolean dealInterest = receiptRecord.getUnusedAmt().compareTo(BigDecimal.ZERO) > 0 && (RentTypeEnum.rent.equals(rentTypeEnum) || RentTypeEnum.interest.equals(rentTypeEnum));
                if (dealInterest) {
                    /**  本次分配金额 by ZC.GUO  **/
                    BigDecimal amount = receiptRecord.getUnusedAmt();
                    if (amount.compareTo(repaymentPlan.getReceivableInterest().subtract(repaymentPlan.getActualInterest())) > 0) {
                        amount = repaymentPlan.getReceivableInterest().subtract(repaymentPlan.getActualInterest());
                    }
                    if (amount.compareTo(BigDecimal.ZERO)>0){
                        repaymentPlan.setActualPaymentDate(batchDate);
                        repaymentPlan.setActualRent(repaymentPlan.getActualRent().add(amount));
                        repaymentPlan.setActualInterest(repaymentPlan.getActualInterest().add(amount));
                        /**  收据明细 by ZC.GUO  **/
                        BasicReceiptDealDetails receiptDealDetails = new BasicReceiptDealDetails();
                        receiptDealDetails.setReceiptId(receiptRecord.getId());
                        if (repaymentPlan.getDueDate().before(DateUtil.endOfDay(batchDate))) {
                            receiptDealDetails.setDealType(DealTypeEnum.normal);
                        } else {
                            receiptDealDetails.setDealType(DealTypeEnum.orderOffset);
                        }
                        receiptDealDetails.setReceiptType(FeeTypeEnum.interest);
                        receiptDealDetails.setDealSource(DealSourceEnum.repaymentPlan);
                        receiptDealDetails.setDealTable(BasicRepaymentPlan.class.getAnnotation(TableName.class).value());
                        receiptDealDetails.setDealId(repaymentPlan.getId());
                        receiptDealDetails.setContractNo(repaymentPlan.getContractNo());
                        receiptDealDetails.setTermNo(repaymentPlan.getTermNo());
                        receiptDealDetails.setDealAmt(amount);
                        /**  TODO ZC.GUO  税金使用价税分离配置 **/
                        receiptDealDetails.setTax(amount.divide(BigDecimal.ONE.add(new BigDecimal("0.06")), 2, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal("0.06")));
                        receiptDealDetails.setStatus(ReceiptStatusEnum.creditSuccess);
                        basicReceiptDealDetailsService.save(receiptDealDetails);
                        penaltyReceiptDealDetailsList.add(receiptDealDetails);

                        /**  收据处理 by ZC.GUO  **/
                        receiptRecord.setUsedAmt(receiptRecord.getUsedAmt().add(amount));
                        receiptRecord.setUnusedAmt(receiptRecord.getUnusedAmt().subtract(amount));

                        /**  利息处理 by ZC.GUO  **/
                        basicAssetsRepaymentPlanService.handleInterest(receiptDealDetails,repaymentPlan, amount,repaymentPlan.getActualInterest(),repaymentPlan.getReceivableInterest(), receiptRecord.getWriteTarget(),batchDate);

                        /**  月供状态 by ZC.GUO  **/
                        if ((repaymentPlan.getReceivableRent().subtract(repaymentPlan.getActualRent())).compareTo(BigDecimal.ZERO) <= 0) {
                            repaymentPlan.setStatus(RepaymentStatusEnum.REPAID);
                            repaymentPlan.setActualPaymentDate(batchDate);
                        }
                        /**  如果是提前还款并且本金已结清 by ZC.GUO  **/
                        if (WriteTargetTypeEnum.beforeCharge.equals(receiptRecord.getWriteTarget()) && repaymentPlan.getReceivablePrinciple().compareTo(repaymentPlan.getActualPrinciple()) <= 0) {
                            repaymentPlan.setStatus(RepaymentStatusEnum.PREPAYMENT);
                            repaymentPlan.setActualPaymentDate(batchDate);
                        }

                        basicRepaymentPlanService.updateById(repaymentPlan);
                    }
                }
                /**  处理本金 by ZC.GUO  **/
                /**  未分配金额大于0且需要处理的是租金或本金，进行分配 by ZC.GUO  **/
                boolean dealCapital = receiptRecord.getUnusedAmt().compareTo(BigDecimal.ZERO) > 0 && (RentTypeEnum.rent.equals(rentTypeEnum) || RentTypeEnum.capital.equals(rentTypeEnum));
                if (dealCapital) {
                    /**  本次分配金额 by ZC.GUO  **/
                    BigDecimal amount = receiptRecord.getUnusedAmt();
                    if (amount.compareTo(repaymentPlan.getReceivablePrinciple().subtract(repaymentPlan.getActualPrinciple())) > 0) {
                        amount = repaymentPlan.getReceivablePrinciple().subtract(repaymentPlan.getActualPrinciple());
                    }
                    if (RepaymentStatusEnum.OVERDUE.equals(repaymentPlan.getStatus())) {
                        specificProvisions = specificProvisions.add(amount);
                    }
                    if (amount.compareTo(BigDecimal.ZERO)>0){
                        repaymentPlan.setActualPaymentDate(batchDate);
                        repaymentPlan.setActualRent(repaymentPlan.getActualRent().add(amount));
                        repaymentPlan.setActualPrinciple(repaymentPlan.getActualPrinciple().add(amount));
                        /**  收据明细 by ZC.GUO  **/
                        BasicReceiptDealDetails receiptDealDetails = new BasicReceiptDealDetails();
                        receiptDealDetails.setReceiptId(receiptRecord.getId());
                        if (repaymentPlan.getDueDate().before(DateUtil.endOfDay(batchDate))) {
                            receiptDealDetails.setDealType(DealTypeEnum.normal);
                        } else {
                            receiptDealDetails.setDealType(DealTypeEnum.orderOffset);
                        }
                        receiptDealDetails.setReceiptType(FeeTypeEnum.capital);
                        receiptDealDetails.setDealSource(DealSourceEnum.repaymentPlan);
                        receiptDealDetails.setDealTable(BasicRepaymentPlan.class.getAnnotation(TableName.class).value());
                        receiptDealDetails.setDealId(repaymentPlan.getId());
                        receiptDealDetails.setContractNo(repaymentPlan.getContractNo());
                        receiptDealDetails.setTermNo(repaymentPlan.getTermNo());
                        receiptDealDetails.setDealAmt(amount);
                        /**  还本金不缴税 **/
                        receiptDealDetails.setTax(BigDecimal.ZERO);
                        receiptDealDetails.setStatus(ReceiptStatusEnum.creditSuccess);
                        basicReceiptDealDetailsService.save(receiptDealDetails);
                        penaltyReceiptDealDetailsList.add(receiptDealDetails);

                        /**  收据处理 by ZC.GUO  **/
                        receiptRecord.setUsedAmt(receiptRecord.getUsedAmt().add(amount));
                        receiptRecord.setUnusedAmt(receiptRecord.getUnusedAmt().subtract(amount));

                        /**  本金处理 by ZC.GUO  **/
                        basicAssetsRepaymentPlanService.handlePrinciple(receiptDealDetails,repaymentPlan, amount,repaymentPlan.getActualPrinciple(),repaymentPlan.getReceivablePrinciple(), receiptRecord.getWriteTarget(),batchDate);

                        /**  月供状态 by ZC.GUO  **/
                        if ((repaymentPlan.getReceivableRent().subtract(repaymentPlan.getActualRent())).compareTo(BigDecimal.ZERO) <= 0) {
                            repaymentPlan.setStatus(RepaymentStatusEnum.REPAID);
                            repaymentPlan.setActualPaymentDate(batchDate);
                        }
                        /**  如果是提前还款并且本金已结清 by ZC.GUO  **/
                        if (WriteTargetTypeEnum.beforeCharge.equals(receiptRecord.getWriteTarget()) && repaymentPlan.getReceivablePrinciple().compareTo(repaymentPlan.getActualPrinciple()) <= 0) {
                            repaymentPlan.setStatus(RepaymentStatusEnum.PREPAYMENT);
                            repaymentPlan.setActualPaymentDate(batchDate);
                        }

                        basicRepaymentPlanService.updateById(repaymentPlan);
                    }
                }
                /**处理专项准备金*/
                basicFinancialAgreement.setSpecificProvisions((basicFinancialAgreement.getSpecificProvisions() != null ?
                        basicFinancialAgreement.getSpecificProvisions() : BigDecimal.ZERO).add(specificProvisions));
                basicFinancialAgreementService.updateById(basicFinancialAgreement);

            }
        }
        return penaltyReceiptDealDetailsList;
    }

    /**
     * 处理预缴款
     *
     * @param
     * @return
     */
    private List<BasicReceiptDealDetails> handleAdvancePayment(BasicReceiptRecord receiptRecord) {
        List<BasicReceiptDealDetails> penaltyReceiptDealDetailsList = new ArrayList<>();
        /**  未分配金额大于0进行分配 by ZC.GUO  **/
        if (!WhetherEnum.YES.getCode().equals(receiptRecord.getIsPrepay()) && receiptRecord.getUnusedAmt().compareTo(BigDecimal.ZERO) > 0) {
            /**  本次分配金额 by ZC.GUO  **/
            BigDecimal amount = receiptRecord.getUnusedAmt();

            /**  生成收据明细 by ZC.GUO  **/
            BasicReceiptDealDetails receiptDealDetails = new BasicReceiptDealDetails();
            receiptDealDetails.setReceiptId(receiptRecord.getId());
            receiptDealDetails.setDealType(DealTypeEnum.unassignedAmt);
            receiptDealDetails.setReceiptType(FeeTypeEnum.unusedFund);
            receiptDealDetails.setDealTable(BasicReceiptRecord.class.getAnnotation(TableName.class).value());
            receiptDealDetails.setDealId(receiptRecord.getId());
            receiptDealDetails.setContractNo(receiptRecord.getContractNo());
            receiptDealDetails.setTermNo(null);
            receiptDealDetails.setDealAmt(amount);
            receiptDealDetails.setTax(amount.divide(BigDecimal.ONE.add(new BigDecimal("0.06")), 2, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal("0.06")));
            receiptDealDetails.setStatus(ReceiptStatusEnum.creditSuccess);
            penaltyReceiptDealDetailsList.add(receiptDealDetails);
        }

        return penaltyReceiptDealDetailsList;
    }

    @Override
    public BasicReceiptRecordVo getReceiptRecordInfo(String contractNo, Long receiptId) {
        BasicReceiptRecord basicReceiptRecord = this.getById(receiptId);
        if (basicReceiptRecord == null) {
            log.error("收据id：{}，收据信息不存在！", receiptId);
            Assert.isTrue(false, "收据id：{}，收据信息不存在！", receiptId);
        }
        BasicMainInfo info = basicMainInfoService.getOne(Wrappers.<BasicMainInfo>lambdaQuery().eq(BasicMainInfo::getContractNo, basicReceiptRecord.getContractNo()), false);
        BasicReceiptRecordVo vo = new BasicReceiptRecordVo();
        if(ContractStatusEnum.writeOff.equals( info.getContractStatus())){
            vo.setWriteOffAmount(basicReceiptRecord.getUsedAmt());
        }
        if(ReceiptStatusEnum.revoke.equals( basicReceiptRecord.getReceiptStatus() )){
            //退款总额/撤销金额
            vo.setCancellationAmount(basicReceiptRecord.getArriveAmt());
        }
        if(ContractStatusEnum.advanceSettle.equals( info.getContractStatus())||ContractStatusEnum.normalSettle.equals( info.getContractStatus())){
            vo.setOverpayment(basicReceiptRecord.getUnusedAmt());
        }
        vo.setUsedAmt(basicReceiptRecord.getUsedAmt());
        vo.setUnusedAmt(basicReceiptRecord.getUnusedAmt());
        //未分配调整金额
        vo.setUnallocatedAdjustmentAmount(basicReceiptRecord.getUnusedAmt());
        BigDecimal rentTotal = BigDecimal.ZERO;
        BigDecimal principleTotal = BigDecimal.ZERO;
        BigDecimal interestTotal = BigDecimal.ZERO;
        BigDecimal amountPaidRentTotal = BigDecimal.ZERO;
        BigDecimal repaymentAmountTotal = BigDecimal.ZERO;
        BigDecimal actualPrinciple = BigDecimal.ZERO;
        BigDecimal actualInterest = BigDecimal.ZERO;

        BigDecimal overdueAmountTotal = BigDecimal.ZERO;
        BigDecimal penaltyAmountPaidTotal = BigDecimal.ZERO;
        BigDecimal penaltyExemptionAmountTotal = BigDecimal.ZERO;
        BigDecimal penaltyRepaymentAmountTotal = BigDecimal.ZERO;

        BigDecimal costAmountTotal = BigDecimal.ZERO;
        BigDecimal costAmountPaidTotal = BigDecimal.ZERO;
        BigDecimal costExemptionAmountTotal = BigDecimal.ZERO;
        BigDecimal costRepaymentAmountTotal = BigDecimal.ZERO;

        //已分配租金
        List<AllocatedRentVo> allocatedRentVos = new ArrayList<>();
        //已分配罚息
        List<AllocatedPenaltyInterestVo> allocatedPenaltyInterestVos = new ArrayList<>();
        //已分配费用
        List<AllocatedCostVo> allocatedCostVos = new ArrayList<>();
        List<BasicReceiptDealDetails> basicReceiptDealDetailsList = basicReceiptDealDetailsService.list(Wrappers.<BasicReceiptDealDetails>query().lambda()
                .eq(BasicReceiptDealDetails::getReceiptId, receiptId).orderByAsc(BasicReceiptDealDetails::getTermNo)
        );
        if (EmptyUtils.isNotEmpty(basicReceiptDealDetailsList)) {
            BasicFinancialAgreement basicFinancialAgreement = basicFinancialAgreementService.getOne(Wrappers.<BasicFinancialAgreement>lambdaQuery()
                    .eq(BasicFinancialAgreement::getContractNo, contractNo)
                    .eq(BasicFinancialAgreement::getCostType, AssetTypeEnum.CAR_AMT));
            for (BasicReceiptDealDetails receiptDealDetails : basicReceiptDealDetailsList) {
                /**  本金 利息 **/
                if (FeeTypeEnum.capital.equals(receiptDealDetails.getReceiptType()) || FeeTypeEnum.interest.equals(receiptDealDetails.getReceiptType())) {
                    boolean flag = false;
                    if (EmptyUtils.isNotEmpty(allocatedRentVos)) {
                        for (AllocatedRentVo rentVo : allocatedRentVos) {
                            if (receiptDealDetails.getTermNo().equals(rentVo.getTermNo())) {
                                flag = true;
                                rentVo.setRepaymentAmount(rentVo.getRepaymentAmount().add(receiptDealDetails.getDealAmt()));
                                repaymentAmountTotal = repaymentAmountTotal.add(receiptDealDetails.getDealAmt());
                                break;
                            }
                        }
                    }
                    if (!flag) {
                        AllocatedRentVo allocatedRentVo = this.getAllocatedRentVo(receiptDealDetails);
                        rentTotal = rentTotal.add(allocatedRentVo.getReceivableRent());
                        principleTotal = principleTotal.add(allocatedRentVo.getReceivablePrinciple());
                        interestTotal = interestTotal.add(allocatedRentVo.getReceivableInterest());
                        amountPaidRentTotal = amountPaidRentTotal.add(allocatedRentVo.getAmountPaid());
                        repaymentAmountTotal = repaymentAmountTotal.add(allocatedRentVo.getRepaymentAmount());
                        actualPrinciple = actualPrinciple.add(allocatedRentVo.getActualPrinciple());
                        actualInterest = actualInterest.add(allocatedRentVo.getActualInterest());
                        allocatedRentVos.add(allocatedRentVo);
                    }
                }

                /**  罚息  **/
                else if (FeeTypeEnum.penalty.equals(receiptDealDetails.getReceiptType())) {
                    //判断是否为空
                    if (EmptyUtils.isNotEmpty(allocatedPenaltyInterestVos)) {
                        break;
                    }
                    boolean flag = false;
                    List<BasicPenaltyInterestDetails> list = basicPenaltyInterestDetailsService.
                            list(Wrappers.<BasicPenaltyInterestDetails>query().lambda().eq(BasicPenaltyInterestDetails::getContractNo, contractNo).
                                    eq(BasicPenaltyInterestDetails::getReceiptId, receiptId).eq(BasicPenaltyInterestDetails::getCostType, FeeTypeEnum.penalty)
                                    .orderByAsc(BasicPenaltyInterestDetails::getTermNo)
                            );
                    for (BasicPenaltyInterestDetails basicPenaltyInterestDetails : list) {
                        for (AllocatedPenaltyInterestVo allocatedPenaltyInterestVo : allocatedPenaltyInterestVos) {
                            if (basicPenaltyInterestDetails.getTermNo().equals(allocatedPenaltyInterestVo.getTermNo())) {
                                flag = true;
                                allocatedPenaltyInterestVo.setRepaymentAmount(allocatedPenaltyInterestVo.getRepaymentAmount().add(basicPenaltyInterestDetails.getAmount()));
                                penaltyRepaymentAmountTotal = penaltyRepaymentAmountTotal.add(receiptDealDetails.getDealAmt());
                                break;
                            }
                        }
                        if (!flag) {
                            AllocatedPenaltyInterestVo allocatedPenaltyInterestVo = this.getAllocatedPenaltyInterestVos(basicPenaltyInterestDetails);
                            allocatedPenaltyInterestVo.setInterestRate(basicFinancialAgreement.getOverDueRate());
                            overdueAmountTotal = overdueAmountTotal.add(allocatedPenaltyInterestVo.getOverdueAmount());
                            penaltyExemptionAmountTotal = penaltyExemptionAmountTotal.add(allocatedPenaltyInterestVo.getExemptionAmount());
                            penaltyAmountPaidTotal = penaltyAmountPaidTotal.add(allocatedPenaltyInterestVo.getAmountPaid());
                            penaltyRepaymentAmountTotal = penaltyRepaymentAmountTotal.add(allocatedPenaltyInterestVo.getRepaymentAmount());
                            allocatedPenaltyInterestVos.add(allocatedPenaltyInterestVo);
                        }
                    }
                }
                /**  费用相关处理  **/
                else {
                    boolean flag = false;
                    if (EmptyUtils.isNotEmpty(allocatedCostVos)) {
                        for (AllocatedCostVo allocatedCostVo : allocatedCostVos) {
                            if (receiptDealDetails.getReceiptType().equals(allocatedCostVo.getFeeType())) {
                                flag = true;
                                allocatedCostVo.setRepaymentAmount(allocatedCostVo.getRepaymentAmount().add(receiptDealDetails.getDealAmt()));
                                costRepaymentAmountTotal = costRepaymentAmountTotal.add(receiptDealDetails.getDealAmt());
                                break;
                            }
                        }
                    }
                    if (!flag) {
                        AllocatedCostVo allocatedCostVo = getAllocatedCostVo(receiptDealDetails);
                        costAmountTotal = costAmountTotal.add(allocatedCostVo.getCostAmount());
                        costAmountPaidTotal = costAmountPaidTotal.add(allocatedCostVo.getAmountPaid());
                        costExemptionAmountTotal = costExemptionAmountTotal.add(allocatedCostVo.getExemptionAmount());
                        costRepaymentAmountTotal = costRepaymentAmountTotal.add(allocatedCostVo.getRepaymentAmount());
                        allocatedCostVos.add(allocatedCostVo);
                    }
                }
            }
        }
        if (EmptyUtils.isNotEmpty(allocatedRentVos)) {
            AllocatedRentVo allocatedRentVo = new AllocatedRentVo();
            allocatedRentVo.setContractNo("总计");
            allocatedRentVo.setReceivableRent(rentTotal);
            allocatedRentVo.setReceivableInterest(interestTotal);
            allocatedRentVo.setReceivablePrinciple(principleTotal);
            allocatedRentVo.setAmountPaid(amountPaidRentTotal);
            allocatedRentVo.setRepaymentAmount(repaymentAmountTotal);
            allocatedRentVo.setActualInterest(actualInterest);
            allocatedRentVo.setActualPrinciple(actualPrinciple);
            allocatedRentVos.add(allocatedRentVo);
            vo.setAllocatedRentVo(allocatedRentVos);
        }
        if (EmptyUtils.isNotEmpty(allocatedPenaltyInterestVos)) {
            AllocatedPenaltyInterestVo allocatedPenaltyInterestVo = new AllocatedPenaltyInterestVo();
            allocatedPenaltyInterestVo.setContractNo("总计");
            allocatedPenaltyInterestVo.setExemptionAmount(penaltyExemptionAmountTotal);
            allocatedPenaltyInterestVo.setOverdueAmount(overdueAmountTotal);
            allocatedPenaltyInterestVo.setAmountPaid(penaltyAmountPaidTotal);
            allocatedPenaltyInterestVo.setRepaymentAmount(penaltyRepaymentAmountTotal);
            allocatedPenaltyInterestVos.add(allocatedPenaltyInterestVo);
            vo.setAllocatedPenaltyInterestVo(allocatedPenaltyInterestVos);
        }
        if (EmptyUtils.isNotEmpty(allocatedCostVos)) {
            AllocatedCostVo allocatedCostVo = new AllocatedCostVo();
            allocatedCostVo.setContractNo("总计");
            allocatedCostVo.setExemptionAmount(costExemptionAmountTotal);
            allocatedCostVo.setCostAmount(costAmountTotal);
            allocatedCostVo.setAmountPaid(costAmountPaidTotal);
            allocatedCostVo.setRepaymentAmount(costRepaymentAmountTotal);
            allocatedCostVos.add(allocatedCostVo);
            vo.setAllocatedCostVo(allocatedCostVos);
        }
        return vo;
    }


    @Override
    public List<CollectCancelVo> getReceiptRecord(ReceiptRecordCondition condition) {
        return this.baseMapper.getReceiptRecordList(condition);
    }

    @Override
    public CollectCancelVo getCollectCancelVo(Long id) {
        BasicReceiptRecord receiptRecord = this.getById(id);
        CollectCancelVo vo = new CollectCancelVo();
        BeanUtil.copyProperties(receiptRecord, vo);
        BasicMainInfo basicMainInfo = basicMainInfoService.getOne(Wrappers.<BasicMainInfo>lambdaQuery().eq(BasicMainInfo::getContractNo, receiptRecord.getContractNo()));
        Assert.isTrue(basicMainInfo != null, MessageFormat.format("合同编号：{0}，合同信息不存在！", receiptRecord.getContractNo()));
        vo.setApplyNo(basicMainInfo.getApplyNo());
        vo.setBusinessType(basicMainInfo.getBusinessType());
        //判断流程发起时，是否时按照时间顺序倒叙撤销，或流程已在流程中不可撤销
        List<BasicReceiptRecord> list = this.list(Wrappers.<BasicReceiptRecord>query().lambda().eq(BasicReceiptRecord::getContractNo, receiptRecord.getContractNo())
                .ne(BasicReceiptRecord::getId, id).
                        and(wrapper1 -> wrapper1.gt(BasicReceiptRecord::getCreateTime, receiptRecord.getCreateTime()).eq(BasicReceiptRecord::getReceiptStatus, ReceiptStatusEnum.creditSuccess)
                                .or(wrapper2 -> wrapper2.eq(BasicReceiptRecord::getReceiptStatus, ReceiptStatusEnum.revokeExamine))
                        ));
        if (EmptyUtils.isNotEmpty(list)) {
            BasicReceiptRecord record = list.get(0);
            log.error(MessageFormat.format("本次撤销不可发起:{0}", record.getReceiptStatus().equals(ReceiptStatusEnum.creditSuccess) ? "需要按照时间顺序倒叙撤销" : "已有撤销合同在流程中"));
            Assert.isTrue(false, MessageFormat.format("本次撤销不可发起:{0}", record.getReceiptStatus().equals(ReceiptStatusEnum.creditSuccess) ? "需要按照时间顺序倒叙撤销" : "已有撤销合同在流程中"));
        }
        return vo;
    }


    private AllocatedRentVo getAllocatedRentVo(BasicReceiptDealDetails receiptDealDetails) {
        AllocatedRentVo allocatedRentVo = new AllocatedRentVo();
        allocatedRentVo.setContractNo(receiptDealDetails.getContractNo());
        allocatedRentVo.setTermNo(receiptDealDetails.getTermNo());
        allocatedRentVo.setRepaymentAmount(receiptDealDetails.getDealAmt());
        if (FeeTypeEnum.interest.equals(receiptDealDetails.getReceiptType())) {
            allocatedRentVo.setActualInterest(allocatedRentVo.getActualInterest().add(receiptDealDetails.getDealAmt()));
        }
        if (FeeTypeEnum.capital.equals(receiptDealDetails.getReceiptType())) {
            allocatedRentVo.setActualPrinciple(allocatedRentVo.getActualPrinciple().add(receiptDealDetails.getDealAmt()));
        }
        BasicRepaymentPlan basicRepaymentPlan = basicRepaymentPlanService.getPlan(receiptDealDetails.getContractNo(), receiptDealDetails.getTermNo());
        allocatedRentVo.setDueDate(basicRepaymentPlan.getDueDate());
        allocatedRentVo.setReceivableRent(basicRepaymentPlan.getReceivableRent());
        allocatedRentVo.setReceivableInterest(basicRepaymentPlan.getReceivableInterest());
        allocatedRentVo.setReceivablePrinciple(basicRepaymentPlan.getReceivablePrinciple());
        allocatedRentVo.setAmountPaid(basicRepaymentPlan.getActualRent());
        return allocatedRentVo;
    }

    /**
     * 处理罚息
     *
     * @param basicPenaltyInterestDetails
     * @return
     */
    private AllocatedPenaltyInterestVo getAllocatedPenaltyInterestVos(BasicPenaltyInterestDetails basicPenaltyInterestDetails) {
        AllocatedPenaltyInterestVo allocatedPenaltyInterestVo = new AllocatedPenaltyInterestVo();
        allocatedPenaltyInterestVo.setContractNo(basicPenaltyInterestDetails.getContractNo());
        allocatedPenaltyInterestVo.setTermNo(basicPenaltyInterestDetails.getTermNo());
        allocatedPenaltyInterestVo.setRepaymentAmount(basicPenaltyInterestDetails.getAmount());
        BasicPenaltyInterest basicPenaltyInterest = basicPenaltyInterestService.getPenaltyInterest(basicPenaltyInterestDetails.getContractNo(), basicPenaltyInterestDetails.getTermNo());
        if (basicPenaltyInterest != null) {
            allocatedPenaltyInterestVo.setOverdueDays(basicPenaltyInterest.getOverdueDays());
            allocatedPenaltyInterestVo.setExemptionAmount(basicPenaltyInterest.getExemptedAmt());
            allocatedPenaltyInterestVo.setInterestRate(basicPenaltyInterest.getOverdueRate());
            allocatedPenaltyInterestVo.setOverdueAmount(basicPenaltyInterest.getTotalPenalty());
            allocatedPenaltyInterestVo.setOverdueDateStart(basicPenaltyInterest.getStartDate());
            allocatedPenaltyInterestVo.setOverdueDateEnd(basicPenaltyInterest.getEndDate());
            allocatedPenaltyInterestVo.setAmountPaid(basicPenaltyInterest.getReceivedAmt());
        }

        return allocatedPenaltyInterestVo;
    }

    /**
     * 处理费用
     *
     * @param receiptDealDetails
     * @return
     */
    private AllocatedCostVo getAllocatedCostVo(BasicReceiptDealDetails receiptDealDetails) {
        AllocatedCostVo allocatedCostVo = new AllocatedCostVo();
        allocatedCostVo.setContractNo(receiptDealDetails.getContractNo());
        allocatedCostVo.setFeeType(receiptDealDetails.getReceiptType());
        allocatedCostVo.setRepaymentAmount(receiptDealDetails.getDealAmt());
        BasicExpenseRecord basicExpenseRecord = basicExpenseRecordService.getOne(Wrappers.<BasicExpenseRecord>lambdaQuery().eq(BasicExpenseRecord::getContractNo, receiptDealDetails.getContractNo()).eq(BasicExpenseRecord::getCostType, receiptDealDetails.getReceiptType()), false);
        if (basicExpenseRecord != null) {
            allocatedCostVo.setExemptionAmount(basicExpenseRecord.getExemptedAmt());
            allocatedCostVo.setCostAmount(basicExpenseRecord.getCostAmt());
            allocatedCostVo.setAmountPaid(basicExpenseRecord.getReceivedAmt());
        }
        return allocatedCostVo;
    }

    private String getBuriedPointNo(BasicReceiptRecord receiptRecord) {
        String buriedPointNo = "";
        //未分配金额是预缴款
        if (WhetherEnum.YES.getCode().equals(receiptRecord.getIsPrepay())) {
            //提前还款核销
            if (WriteTargetTypeEnum.beforeCharge.equals(receiptRecord.getWriteTarget())) {
                buriedPointNo = VoucherBuriedPointNo.settlementAdvancePayment;
            } //正常核销
            else if (WriteTargetTypeEnum.normal.equals(receiptRecord.getWriteTarget())) {
                buriedPointNo = VoucherBuriedPointNo.advancePaymentSettlementRent;
            }
        } else {
            //对公结算及提前还款核销
            if (ReceiptSourceTypeEnum.transferAccounts.equals(receiptRecord.getSourceType()) && WriteTargetTypeEnum.beforeCharge.equals(receiptRecord.getWriteTarget())) {
                buriedPointNo = VoucherBuriedPointNo.corporateSettlementAdvance;
            } //对公结算及正常核销
            else if (ReceiptSourceTypeEnum.transferAccounts.equals(receiptRecord.getSourceType()) && WriteTargetTypeEnum.normal.equals(receiptRecord.getWriteTarget())) {
                buriedPointNo = VoucherBuriedPointNo.corporateSettlement;
            }//银行代扣及提前还款核销
            else if (ReceiptSourceTypeEnum.bankDeduct.equals(receiptRecord.getSourceType()) && WriteTargetTypeEnum.beforeCharge.equals(receiptRecord.getWriteTarget())) {
                buriedPointNo = VoucherBuriedPointNo.withholdSettlementAdvance;
            }//银行代扣及正常核销
            else if (ReceiptSourceTypeEnum.bankDeduct.equals(receiptRecord.getSourceType()) && WriteTargetTypeEnum.normal.equals(receiptRecord.getWriteTarget())) {
                buriedPointNo = VoucherBuriedPointNo.contractWithhold;
            }

        }
        return buriedPointNo;
    }

    //预缴款收入处理
    @Override
    public void handleIncome(Long receiptId, ReceiptSourceTypeEnum sourceType) {
        BasicReceiptRecord receiptRecord = this.getById(receiptId);
        BasicReceiptRecord basicReceiptRecord =new BasicReceiptRecord();
        BeanUtil.copyProperties(receiptRecord,basicReceiptRecord,"id","createBy","createTime","updateBy","updateTime");
        /**  发送扣款成功数据到账务服务  **/
        AfsUser user = SecurityUtils.getUser();
        String operator = user == null ? null : user.getUsername();
        String buriedPointNo = null;
        WriteTargetTypeEnum writeTargetType = handleWriteTargetType( basicReceiptRecord.getContractNo() );
        basicReceiptRecord.setWriteTarget( writeTargetType );
        if (WriteTargetTypeEnum.beforeCharge.equals( basicReceiptRecord.getWriteTarget() )) {
            buriedPointNo = VoucherBuriedPointNo.withholdSettlementAdvance;
        } else {
            buriedPointNo = VoucherBuriedPointNo.contractWithhold;
        }
        basicReceiptRecord.setIsPrepay( WhetherEnum.YES.getCode() );
        basicReceiptRecord.setUnusedAmt(basicReceiptRecord.getArriveAmt() );
        basicReceiptRecord.setUsedAmt( BigDecimal.ZERO );
        basicReceiptRecord.setOuterAmt( BigDecimal.ZERO );
        basicReceiptRecord.setSpecialOuterAmt( BigDecimal.ZERO );
        //判断核销类型
        TransOpreateTypeEnums operateType = null;
        if (ReceiptSourceTypeEnum.bankDeduct.equals(sourceType)) {
            operateType = TransOpreateTypeEnums.debit;
        } else if (ReceiptSourceTypeEnum.wechatRepayment.equals(sourceType)) {
            operateType = TransOpreateTypeEnums.wechatrepay;
        } else {
            log.error(MessageFormat.format("来源类型不符:{0}", sourceType));
            Assert.isTrue(false, MessageFormat.format("来源类型不符:{0}", sourceType));
        }
        basicReceiptRecord.setReceiptStatus(ReceiptStatusEnum.creditSuccess);
        this.save(basicReceiptRecord);
        this.sendDebitSuccessDataToFinance(basicReceiptRecord, operateType, buriedPointNo, operator);

    }


    public WriteTargetTypeEnum handleWriteTargetType(String contractNo) {
        /**  查询合同的不可扣款的提前还款扣款指令 by ZC.GUO  **/
        BasicDebitRecord basicDebitRecord = basicDebitRecordService.getOne(Wrappers.<BasicDebitRecord>query().lambda()
                .eq(BasicDebitRecord::getFeeType, FeeTypeEnum.advanceSettle)
                .eq(BasicDebitRecord::getContractNo, contractNo)
        );
        if (EmptyUtils.isNotEmpty(basicDebitRecord)) {
            if (DebitStatusEnum.notMayDebit.equals(basicDebitRecord.getDebitStatus())) {
                /**  提前结清报价失效 by ZC.GUO  **/
                custChangeFeign.prepaymentRecordInvalid(basicDebitRecord.getContractNo());
                /**  本提前结清扣款指令删除 by ZC.GUO  **/
                basicDebitRecordService.removeById(basicDebitRecord.getId());
                return WriteTargetTypeEnum.normal;
            } else {
                return WriteTargetTypeEnum.beforeCharge;
            }
        } else {
            return WriteTargetTypeEnum.normal;
        }
    }

    /**
     * 定时发送合同关闭数据
     */
    @Override
    public void sendcontractClose() {
        List<BasicMainInfo> basicMainInfoList = basicMainInfoService.list(Wrappers.<BasicMainInfo>query().lambda().isNull(BasicMainInfo::getCloseDate)
                .and(wrapper -> wrapper.ne(BasicMainInfo::getSendStatus, YesOrNoEnum.yes)
                        .or().isNull(BasicMainInfo::getSendStatus))
                .and(wrapper -> wrapper.eq(BasicMainInfo::getContractStatus, ContractStatusEnum.advanceSettle)
                        .or().eq(BasicMainInfo::getContractStatus, ContractStatusEnum.normalSettle))
        );
        for (BasicMainInfo basicMainInfo : basicMainInfoList) {
            try {
                handleContractClose(basicMainInfo);
            } catch (Exception e) {
                log.error("发送合同关闭数据异常,异常信息:[{}]", e);
            }
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void handleContractClose(BasicMainInfo basicMainInfo) {
        List<BasicReceiptRecord> basicReceiptRecords = this.list(Wrappers.<BasicReceiptRecord>query().lambda().ne(BasicReceiptRecord::getReceiptStatus, ReceiptStatusEnum.revoke)
                .eq(BasicReceiptRecord::getContractNo,basicMainInfo.getContractNo()).gt(BasicReceiptRecord::getUnusedAmt, BigDecimal.ZERO)
        );
        /** 差额/溢缴款金额 */
        BigDecimal amount = BigDecimal.ZERO;
        OverpaymentDifferenceDTO dto = convertFromDto(basicMainInfo);
        String custNo = "";
        if (EmptyUtils.isNotEmpty(basicReceiptRecords)) {
            for (BasicReceiptRecord basicReceiptRecord : basicReceiptRecords) {
                amount = amount.add(basicReceiptRecord.getUnusedAmt());
                custNo = basicReceiptRecord.getCustNo();
            }
            dto.setProcessStatus(ProcessStatusEnum.draft);
        } else {
            BasicContractCustRelation basicContractCustRelation = basicContractCustRelationService
                    .getOne(Wrappers.<BasicContractCustRelation>query().lambda()
                            .eq(BasicContractCustRelation::getContractNo, basicMainInfo.getContractNo())
                            .eq(BasicContractCustRelation::getCustRole, PersonRoleTypeEnum.MAIN_PERSON));
            custNo = basicContractCustRelation.getCustNo();
            dto.setProcessStatus(ProcessStatusEnum.approved);
        }
        dto.setCustNo(custNo);
        dto.setType(OverpaymentDifferenceTypeEnum.OVERPAYMENT);
        dto.setAmount(amount);
        basicMainInfo.setSendStatus(YesOrNoEnum.yes);
//        basicMainInfoService.updateById(basicMainInfo);
        IResponse iResponse = OverpaymentDifferenceFeign.saveManageOverpaymentDifference(dto);
        Assert.isTrue(CommonConstants.SUCCESS.equals(iResponse.getCode()), "发送合同关闭数据失败");
        basicMainInfoService.updateById(basicMainInfo);

    }

    public static OverpaymentDifferenceDTO convertFromDto(BasicMainInfo basicMainInfo) {
        OverpaymentDifferenceDTO overpaymentDifferenceDTO = new OverpaymentDifferenceDTO();
        overpaymentDifferenceDTO.setApplyNo(basicMainInfo.getApplyNo());
        overpaymentDifferenceDTO.setContractNo(basicMainInfo.getContractNo());
        overpaymentDifferenceDTO.setDataSource(DataSourceEnum.icos);
        overpaymentDifferenceDTO.setContractStatus(basicMainInfo.getContractStatus());
        overpaymentDifferenceDTO.setChannelFullName(basicMainInfo.getChannelFullName());
        overpaymentDifferenceDTO.setChannelType(basicMainInfo.getChannelType());
        overpaymentDifferenceDTO.setProductName(basicMainInfo.getProductName());
        overpaymentDifferenceDTO.setStartDate(basicMainInfo.getStartDate());
        overpaymentDifferenceDTO.setEndDate(basicMainInfo.getEndDate());
        return overpaymentDifferenceDTO;
    }

    //修改状态
    private void updateContractStatus(String contractNo,WriteTargetTypeEnum writeTarget) {
        List<BasicRepaymentPlan> list = basicRepaymentPlanService.list(Wrappers.<BasicRepaymentPlan>query().lambda()
                .eq(BasicRepaymentPlan::getContractNo, contractNo)
                .eq(BasicRepaymentPlan::getStatus, RepaymentStatusEnum.OVERDUE));
        BasicMainInfo basicMainInfo = basicMainInfoService.getOne(Wrappers.<BasicMainInfo>query().lambda()
                .eq(BasicMainInfo::getContractNo, contractNo)
        );
        basicMainInfo.setSendStatus(YesOrNoEnum.no);
        if(EmptyUtils.isNotEmpty( list )){
            BasicDebitInfo basicDebitInfo = basicDebitInfoService.getOne(Wrappers.<BasicDebitInfo>lambdaQuery().eq(BasicDebitInfo::getContractNo, contractNo));
            if (YesOrNoEnum.yes.equals(basicDebitInfo.getIsOverdue())) {
                basicDebitInfo.setIsOverdue(YesOrNoEnum.yes);
                basicDebitInfoService.updateById(basicDebitInfo);
            }
            if (!ContractStatusEnum.overdue.equals(basicMainInfo.getContractStatus())) {
                basicMainInfo.setContractStatus(ContractStatusEnum.overdue);
                basicMainInfoService.updateById(basicMainInfo);
            }
        }else if(WriteTargetTypeEnum.beforeCharge.equals(writeTarget)){
            basicMainInfo.setContractStatus(ContractStatusEnum.contractEffective);
        }
        basicMainInfoService.updateById(basicMainInfo);
    }
}
